1 //-----------------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //-----------------------------------------------------------------------------
4 namespace System.ServiceModel.ComIntegration
5 {
6     using System;
7     using System.Diagnostics;
8     using System.Runtime;
9     using System.Runtime.InteropServices;
10     using System.ServiceModel.Diagnostics;
11     using System.Threading;
12 
13     class ComPlusSynchronizationContext : SynchronizationContext
14     {
15         IServiceActivity activity;
16         bool postSynchronous;
17 
ComPlusSynchronizationContext(IServiceActivity activity, bool postSynchronous)18         public ComPlusSynchronizationContext(IServiceActivity activity,
19                                              bool postSynchronous)
20         {
21             this.activity = activity;
22             this.postSynchronous = postSynchronous;
23         }
24 
Send(SendOrPostCallback d, Object state)25         public override void Send(SendOrPostCallback d, Object state)
26         {
27             Fx.Assert("Send should never be called");
28         }
29 
Post(SendOrPostCallback d, Object state)30         public override void Post(SendOrPostCallback d, Object state)
31         {
32             ComPlusActivityTrace.Trace(TraceEventType.Verbose, TraceCode.ComIntegrationEnteringActivity,
33                         SR.TraceCodeComIntegrationEnteringActivity);
34 
35             ServiceCall call = new ServiceCall(d, state);
36             if (this.postSynchronous)
37             {
38                 this.activity.SynchronousCall(call);
39             }
40             else
41             {
42                 this.activity.AsynchronousCall(call);
43             }
44             ComPlusActivityTrace.Trace(TraceEventType.Verbose, TraceCode.ComIntegrationLeftActivity,
45                         SR.TraceCodeComIntegrationLeftActivity);
46         }
47 
Dispose()48         public void Dispose()
49         {
50             while (Marshal.ReleaseComObject(this.activity) > 0);
51         }
52 
53         class ServiceCall : IServiceCall
54         {
55             SendOrPostCallback callback;
56             Object state;
57 
ServiceCall(SendOrPostCallback callback, Object state)58             public ServiceCall(SendOrPostCallback callback,
59                                Object state)
60             {
61                 this.callback = callback;
62                 this.state = state;
63             }
64 
65 
66 
OnCall()67             public void OnCall()
68             {
69                 ServiceModelActivity activity = null;
70                 try
71                 {
72                     Guid guidLogicalThreadID = Guid.Empty;
73 
74                     if (DiagnosticUtility.ShouldUseActivity)
75                     {
76                         IComThreadingInfo comThreadingInfo;
77                         comThreadingInfo = (IComThreadingInfo)SafeNativeMethods.CoGetObjectContext(ComPlusActivityTrace.IID_IComThreadingInfo);
78 
79                         if (comThreadingInfo != null)
80                         {
81 
82                             comThreadingInfo.GetCurrentLogicalThreadId(out guidLogicalThreadID);
83 
84                             activity = ServiceModelActivity.CreateBoundedActivity(guidLogicalThreadID);
85                         }
86                         ServiceModelActivity.Start(activity, SR.GetString(SR.TransferringToComplus, guidLogicalThreadID.ToString()), ActivityType.TransferToComPlus);
87                     }
88                     ComPlusActivityTrace.Trace(TraceEventType.Verbose, TraceCode.ComIntegrationExecutingCall, SR.TraceCodeComIntegrationExecutingCall);
89 
90                     this.callback(this.state);
91                 }
92                 catch (Exception e)
93                 {
94                     if (Fx.IsFatal(e))
95                         throw;
96 
97                     DiagnosticUtility.InvokeFinalHandler(e);
98                 }
99                 finally
100                 {
101                     if (activity != null)
102                     {
103                         activity.Dispose();
104                         activity = null;
105                     }
106                 }
107             }
108         }
109     }
110 }
111