| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace System.ServiceModel.ComIntegration
- {
- using System;
- using System.Runtime.Diagnostics;
- using System.ServiceModel.Channels;
- using System.ServiceModel.Dispatcher;
- using System.ServiceModel.Description;
- using System.Security.Principal;
- using System.ServiceModel;
- using System.Transactions;
- using System.Diagnostics;
- using System.ServiceModel.Diagnostics;
- using System.EnterpriseServices;
- using SR = System.ServiceModel.SR;
- using System.Globalization;
- class ComPlusThreadInitializer : ICallContextInitializer
- {
- ServiceInfo info;
- ComPlusAuthorization comAuth;
- Guid iid;
- public ComPlusThreadInitializer(ContractDescription contract,
- DispatchOperation operation,
- ServiceInfo info)
- {
- this.info = info;
- iid = contract.ContractType.GUID;
- if (info.CheckRoles)
- {
- string[] serviceRoleMembers = null;
- string[] contractRoleMembers = null;
- string[] operationRoleMembers = null;
- // Figure out the role members we want...
- //
- serviceRoleMembers = info.ComponentRoleMembers;
- foreach (ContractInfo contractInfo in this.info.Contracts)
- {
- if (contractInfo.IID == iid)
- {
- contractRoleMembers = contractInfo.InterfaceRoleMembers;
- foreach (OperationInfo opInfo in contractInfo.Operations)
- {
- if (opInfo.Name == operation.Name)
- {
- operationRoleMembers = opInfo.MethodRoleMembers;
- break;
- }
- }
- if (operationRoleMembers == null)
- {
- // Did not find the operation
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ListenerInitFailed(
- SR.GetString(SR.ComOperationNotFound,
- contract.Name,
- operation.Name)));
- }
- break;
- }
- }
- this.comAuth = new ComPlusAuthorization(serviceRoleMembers,
- contractRoleMembers,
- operationRoleMembers);
- }
- }
- public object BeforeInvoke(
- InstanceContext instanceContext,
- IClientChannel channel,
- Message message)
- {
- ComPlusServerSecurity serverSecurity = null;
- WindowsImpersonationContext impersonateContext = null;
- bool errorTraced = false;
- WindowsIdentity identity = null;
- Uri from = null;
- object instance = null;
- int instanceID = 0;
- string action = null;
- TransactionProxy proxy = null;
- Transaction tx = null;
- Guid incomingTransactionID = Guid.Empty;
- // The outer try block is to comply with FXCOP's WrapVulnerableFinallyClausesInOuterTry rule.
- try
- {
- try
- {
- identity = MessageUtil.GetMessageIdentity(message);
- if (message.Headers.From != null)
- from = message.Headers.From.Uri;
- instance = instanceContext.GetServiceInstance(message);
- instanceID = instance.GetHashCode();
- action = message.Headers.Action;
- ComPlusMethodCallTrace.Trace(TraceEventType.Verbose, TraceCode.ComIntegrationInvokingMethod,
- SR.TraceCodeComIntegrationInvokingMethod, this.info, from, action, identity.Name, iid, instanceID, false);
- // Security
- //
- if (this.info.CheckRoles)
- {
- if (!this.comAuth.IsAuthorizedForOperation(identity))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.CallAccessDenied());
- }
- }
- if (this.info.HostingMode != HostingMode.WebHostOutOfProcess)
- {
- // NOTE: This has the side effect of setting up
- // the COM server security thing, so be sure
- // to clear it with Dispose() eventually.
- //
- serverSecurity = new ComPlusServerSecurity(identity,
- this.info.CheckRoles);
- }
- // Transactions
- //
- proxy = instanceContext.Extensions.Find<TransactionProxy>();
- if (proxy != null)
- {
- // This makes the Tx header Understood.
- tx = MessageUtil.GetMessageTransaction(message);
- if (tx != null)
- {
- incomingTransactionID = tx.TransactionInformation.DistributedIdentifier;
- }
- try
- {
- if (tx != null)
- {
- proxy.SetTransaction(tx);
- }
- else
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.TransactionMismatch());
- }
- ComPlusMethodCallTrace.Trace(TraceEventType.Verbose, TraceCode.ComIntegrationInvokingMethodNewTransaction,
- SR.TraceCodeComIntegrationInvokingMethodNewTransaction, this.info, from, action, identity.Name, iid, instanceID, incomingTransactionID);
- }
- catch (FaultException e)
- {
- Transaction txProxy = proxy.CurrentTransaction;
- Guid currentTransactionID = Guid.Empty;
- if (txProxy != null)
- currentTransactionID = txProxy.TransactionInformation.DistributedIdentifier;
- string identityName = String.Empty;
- if (null != identity)
- identityName = identity.Name;
- DiagnosticUtility.EventLog.LogEvent(TraceEventType.Error,
- (ushort)System.Runtime.Diagnostics.EventLogCategory.ComPlus,
- (uint)System.Runtime.Diagnostics.EventLogEventId.ComPlusInvokingMethodFailedMismatchedTransactions,
- incomingTransactionID.ToString("B").ToUpperInvariant(),
- currentTransactionID.ToString("B").ToUpperInvariant(),
- from.ToString(),
- this.info.AppID.ToString("B").ToUpperInvariant(),
- this.info.Clsid.ToString("B").ToUpperInvariant(),
- iid.ToString(),
- action,
- instanceID.ToString(CultureInfo.InvariantCulture),
- System.Threading.Thread.CurrentThread.ManagedThreadId.ToString(CultureInfo.InvariantCulture),
- SafeNativeMethods.GetCurrentThreadId().ToString(CultureInfo.InvariantCulture),
- identityName,
- e.ToString());
- errorTraced = true;
- throw;
- }
- }
- else
- {
- ComPlusMethodCallTrace.Trace(TraceEventType.Verbose, TraceCode.ComIntegrationInvokingMethodContextTransaction,
- SR.TraceCodeComIntegrationInvokingMethodContextTransaction, this.info, from, action, identity.Name, iid, instanceID, true);
- }
- // Impersonation
- //
- if (this.info.HostingMode == HostingMode.WebHostOutOfProcess)
- {
- impersonateContext = identity.Impersonate();
- }
- CorrelationState correlationState;
- correlationState = new CorrelationState(impersonateContext,
- serverSecurity,
- from,
- action,
- identity.Name,
- instanceID);
- impersonateContext = null;
- serverSecurity = null;
- return correlationState;
- }
- finally
- {
- if (impersonateContext != null)
- impersonateContext.Undo();
- if (serverSecurity != null)
- ((IDisposable)serverSecurity).Dispose();
- }
- }
- catch (Exception e)
- {
- if (errorTraced == false)
- {
- if (DiagnosticUtility.ShouldTraceError)
- {
- DiagnosticUtility.EventLog.LogEvent(TraceEventType.Error,
- (ushort)System.Runtime.Diagnostics.EventLogCategory.ComPlus,
- (uint)System.Runtime.Diagnostics.EventLogEventId.ComPlusInvokingMethodFailed,
- from == null ? string.Empty : from.ToString(),
- this.info.AppID.ToString("B").ToUpperInvariant(),
- this.info.Clsid.ToString("B").ToUpperInvariant(),
- iid.ToString("B").ToUpperInvariant(),
- action,
- instanceID.ToString(CultureInfo.InvariantCulture),
- System.Threading.Thread.CurrentThread.ManagedThreadId.ToString(CultureInfo.InvariantCulture),
- SafeNativeMethods.GetCurrentThreadId().ToString(CultureInfo.InvariantCulture),
- identity.Name,
- e.ToString());
- }
- }
- throw;
- }
- }
- public void AfterInvoke(object correlationState)
- {
- CorrelationState state = (CorrelationState)correlationState;
- if (state != null)
- {
- ComPlusMethodCallTrace.Trace(TraceEventType.Verbose, TraceCode.ComIntegrationInvokedMethod,
- SR.TraceCodeComIntegrationInvokedMethod, this.info, state.From, state.Action, state.CallerIdentity, iid, state.InstanceID, false);
- state.Cleanup();
- }
- }
- class CorrelationState
- {
- WindowsImpersonationContext impersonationContext;
- ComPlusServerSecurity serverSecurity;
- Uri from;
- string action;
- string callerIdentity;
- int instanceID;
- public CorrelationState(WindowsImpersonationContext context,
- ComPlusServerSecurity serverSecurity,
- Uri from,
- string action,
- string callerIdentity,
- int instanceID)
- {
- this.impersonationContext = context;
- this.serverSecurity = serverSecurity;
- this.from = from;
- this.action = action;
- this.callerIdentity = callerIdentity;
- this.instanceID = instanceID;
- }
- public Uri From
- {
- get
- {
- return this.from;
- }
- }
- public string Action
- {
- get
- {
- return this.action;
- }
- }
- public string CallerIdentity
- {
- get
- {
- return this.callerIdentity;
- }
- }
- public int InstanceID
- {
- get
- {
- return this.instanceID;
- }
- }
- public void Cleanup()
- {
- if (this.impersonationContext != null)
- this.impersonationContext.Undo();
- if (this.serverSecurity != null)
- ((IDisposable)this.serverSecurity).Dispose();
- }
- }
- }
- }
|