| File: ClrDataExceptionState.cs | Web Access |
| Project: src\runtime\src\native\managed\cdac\Microsoft.Diagnostics.DataContractReader.Legacy\Microsoft.Diagnostics.DataContractReader.Legacy.csproj (Microsoft.Diagnostics.DataContractReader.Legacy) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Diagnostics; using System.Runtime.InteropServices.Marshalling; using Microsoft.Diagnostics.DataContractReader.Contracts; namespace Microsoft.Diagnostics.DataContractReader.Legacy; [GeneratedComClass] public sealed unsafe partial class ClrDataExceptionState : IXCLRDataExceptionState { private readonly Target _target; private readonly TargetPointer _threadAddress; private readonly uint _flags; private readonly TargetPointer _thrownObjectHandle; private readonly TargetPointer _previousExInfoAddress; private readonly IXCLRDataExceptionState? _legacyImpl; public ClrDataExceptionState( Target target, TargetPointer threadAddress, uint flags, TargetPointer thrownObjectHandle, TargetPointer previousExInfoAddress, IXCLRDataExceptionState? legacyImpl) { _target = target; _threadAddress = threadAddress; _flags = flags; _thrownObjectHandle = thrownObjectHandle; _previousExInfoAddress = previousExInfoAddress; _legacyImpl = legacyImpl; } int IXCLRDataExceptionState.GetFlags(uint* flags) { int hr = HResults.S_OK; try { if (flags is null) throw new ArgumentNullException(nameof(flags)); *flags = _flags; if (_previousExInfoAddress != TargetPointer.Null) *flags |= (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_NESTED; } catch (System.Exception ex) { hr = ex.HResult; } #if DEBUG if (_legacyImpl is not null) { uint legacyFlags; int hrLocal = _legacyImpl.GetFlags(&legacyFlags); Debug.ValidateHResult(hr, hrLocal); if (hr == HResults.S_OK) Debug.Assert(*flags == legacyFlags, $"cDAC flags: {*flags:x}, DAC flags: {legacyFlags:x}"); } #endif return hr; } int IXCLRDataExceptionState.GetPrevious(DacComNullableByRef<IXCLRDataExceptionState> exState) { int hr = HResults.S_OK, hrLocal = HResults.S_OK; IXCLRDataExceptionState? legacyPrevious = null; if (_legacyImpl is not null) { DacComNullableByRef<IXCLRDataExceptionState> legacyPreviousOut = new(isNullRef: false); hrLocal = _legacyImpl.GetPrevious(legacyPreviousOut); legacyPrevious = legacyPreviousOut.Interface; } try { if (_previousExInfoAddress == TargetPointer.Null) { hr = HResults.S_FALSE; } else { _target.Contracts.Exception.GetNestedExceptionInfo( _previousExInfoAddress, out TargetPointer nextNestedException, out TargetPointer prevExThrownObjectHandle); exState.Interface = new ClrDataExceptionState( _target, _threadAddress, (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_DEFAULT, prevExThrownObjectHandle, nextNestedException, legacyPrevious ); } } catch (System.Exception ex) { hr = ex.HResult; } #if DEBUG if (_legacyImpl is not null) { Debug.ValidateHResult(hr, hrLocal); } #endif return hr; } int IXCLRDataExceptionState.GetManagedObject(DacComNullableByRef<IXCLRDataValue> value) => LegacyFallbackHelper.CanFallback() && _legacyImpl is not null ? _legacyImpl.GetManagedObject(value) : HResults.E_NOTIMPL; int IXCLRDataExceptionState.GetBaseType(/*CLRDataBaseExceptionType*/ uint* type) => HResults.E_NOTIMPL; int IXCLRDataExceptionState.GetCode(uint* code) => HResults.E_NOTIMPL; int IXCLRDataExceptionState.GetString(uint bufLen, uint* strLen, char* str) { int hr = HResults.S_OK; try { TargetPointer exceptionObject = _target.ReadPointer(_thrownObjectHandle); ExceptionData exceptionData = _target.Contracts.Exception.GetExceptionData(exceptionObject); if (exceptionData.Message == TargetPointer.Null) { if (strLen is not null) { *strLen = 0; } if (bufLen >= 1) { if (str is null) { hr = HResults.E_INVALIDARG; } else { str[0] = '\0'; } } } else { string message = _target.Contracts.Object.GetStringValue(exceptionData.Message); OutputBufferHelpers.CopyStringToBuffer(str, bufLen, strLen, message); if (str is not null && bufLen < (uint)(message.Length + 1)) hr = HResults.S_FALSE; } } catch (System.Exception ex) { hr = ex.HResult; } #if DEBUG if (_legacyImpl is not null) { char[] strLocal = new char[Math.Max((int)bufLen, 1)]; uint legacyStrLen; int hrLocal; fixed (char* strLocalPtr = strLocal) { hrLocal = _legacyImpl.GetString(bufLen, &legacyStrLen, str is null ? null : strLocalPtr); } Debug.ValidateHResult(hr, hrLocal); if (hr >= 0) { Debug.Assert(strLen == null || *strLen == legacyStrLen); int cmpLen = Math.Min((int)legacyStrLen, (int)bufLen) - 1; Debug.Assert(str == null || cmpLen <= 0 || new ReadOnlySpan<char>(strLocal, 0, cmpLen).SequenceEqual(new ReadOnlySpan<char>(str, cmpLen))); } } #endif return hr; } int IXCLRDataExceptionState.Request(uint reqCode, uint inBufferSize, byte* inBuffer, uint outBufferSize, byte* outBuffer) { int hr = HResults.E_INVALIDARG; if (reqCode == (uint)CLRDataGeneralRequest.CLRDATA_REQUEST_REVISION) { if (inBufferSize == 0 && inBuffer is null && outBufferSize == sizeof(uint) && outBuffer is not null) { *(uint*)outBuffer = 2; hr = HResults.S_OK; } } #if DEBUG if (_legacyImpl is not null) { byte[] localBuffer = new byte[(int)outBufferSize]; fixed (byte* localOutBuffer = localBuffer) { int hrLocal = _legacyImpl.Request(reqCode, inBufferSize, inBuffer, outBufferSize, localOutBuffer); Debug.ValidateHResult(hr, hrLocal); if (hr == HResults.S_OK && reqCode == (uint)CLRDataGeneralRequest.CLRDATA_REQUEST_REVISION) { Debug.Assert(outBufferSize == sizeof(uint) && outBuffer is not null); uint legacyRevision = *(uint*)localOutBuffer; uint revision = *(uint*)outBuffer; Debug.Assert(revision == legacyRevision); } } } #endif return hr; } int IXCLRDataExceptionState.IsSameState(EXCEPTION_RECORD64* exRecord, uint contextSize, byte* cxRecord) => LegacyFallbackHelper.CanFallback() && _legacyImpl is not null ? _legacyImpl.IsSameState(exRecord, contextSize, cxRecord) : HResults.E_NOTIMPL; int IXCLRDataExceptionState.IsSameState2(uint flags, EXCEPTION_RECORD64* exRecord, uint contextSize, byte* cxRecord) => LegacyFallbackHelper.CanFallback() && _legacyImpl is not null ? _legacyImpl.IsSameState2(flags, exRecord, contextSize, cxRecord) : HResults.E_NOTIMPL; int IXCLRDataExceptionState.GetTask(DacComNullableByRef<IXCLRDataTask> task) { int hr = HResults.S_OK, hrLocal = HResults.S_OK; IXCLRDataTask? legacyTask = null; if (_legacyImpl is not null) { DacComNullableByRef<IXCLRDataTask> legacyTaskOut = new(isNullRef: false); hrLocal = _legacyImpl.GetTask(legacyTaskOut); legacyTask = legacyTaskOut.Interface; } try { task.Interface = new ClrDataTask(_threadAddress, _target, legacyTask); } catch (System.Exception ex) { hr = ex.HResult; } #if DEBUG if (_legacyImpl is not null) { Debug.ValidateHResult(hr, hrLocal); } #endif return hr; } }