// Licensed to the .NET Foundation under one or more 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.Runtime.Remoting.Messaging;
using System.Security;

namespace System.Diagnostics
{
    // this code is specific to .NET 4.5 and uses CallContext to store Activity.Current which requires Activity to be Serializable.
    [Serializable] // DO NOT remove
    public partial class Activity
    {
        /// <summary>
        /// Returns the current operation (Activity) for the current thread.  This flows 
        /// across async calls.
        /// </summary>
        public static Activity Current
        {
#if ALLOW_PARTIALLY_TRUSTED_CALLERS
            [System.Security.SecuritySafeCriticalAttribute]
#endif
            get
            {
                return (Activity)CallContext.LogicalGetData(FieldKey);
            }
            
#if ALLOW_PARTIALLY_TRUSTED_CALLERS
            [System.Security.SecuritySafeCriticalAttribute]
#endif
            private set
            {
                CallContext.LogicalSetData(FieldKey, value);
            }
        }

#region private

        [Serializable] // DO NOT remove
        private partial class KeyValueListNode
        {
        }

        private static readonly string FieldKey = $"{typeof(Activity).FullName}";
#endregion
    }
}
// Licensed to the .NET Foundation under one or more 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.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;
using System.Security;

namespace System.Diagnostics
{
    public partial class Activity
    {
        /// <summary>
        /// Returns the current operation (Activity) for the current thread.  This flows 
        /// across async calls.
        /// </summary>
        public static Activity Current
        {
#if ALLOW_PARTIALLY_TRUSTED_CALLERS
            [System.Security.SecuritySafeCriticalAttribute]
#endif
            get
            {
                ObjectHandle activityHandle = (ObjectHandle)CallContext.LogicalGetData(FieldKey);
                
                // Unwrap the Activity if it was set in the same AppDomain (as FieldKey is AppDomain-specific). 
                if (activityHandle != null)
                {
                    return (Activity)activityHandle.Unwrap();
                }
                return null;
            }
            
#if ALLOW_PARTIALLY_TRUSTED_CALLERS
            [System.Security.SecuritySafeCriticalAttribute]
#endif
            private set
            {
                // Applications may implicitly or explicitly call other AppDomains
                // that do not have DiagnosticSource DLL, therefore may not be able to resolve Activity type stored in the logical call context. 
                // To avoid it, we wrap Activity with ObjectHandle.
                CallContext.LogicalSetData(FieldKey, new ObjectHandle(value));
            }
        }

#region private

        private partial class KeyValueListNode
        {
        }

        // Slot name depends on the AppDomain Id in order to prevent AppDomains to use the same Activity
        // Cross AppDomain calls are considered as 'external' i.e. only Activity Id and Baggage should be propagated and 
        // new Activity should be started for the RPC calls (incoming and outgoing) 
        private static readonly string FieldKey = $"{typeof(Activity).FullName}_{AppDomain.CurrentDomain.Id}";
#endregion
    }
}
Store ObjectHandle in LogicalCallContext and prevent cross AppDomain Activity usage
Store ObjectHandle in LogicalCallContext and prevent cross AppDomain Activity usage
