182 lines
7.4 KiB
C#
182 lines
7.4 KiB
C#
|
//-----------------------------------------------------------------------------
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
namespace System.ServiceModel.ComIntegration
|
||
|
{
|
||
|
using System;
|
||
|
using System.Diagnostics;
|
||
|
using System.Diagnostics.CodeAnalysis;
|
||
|
using System.EnterpriseServices;
|
||
|
using System.Runtime;
|
||
|
using System.Runtime.Diagnostics;
|
||
|
using System.Runtime.InteropServices;
|
||
|
using System.Security.Principal;
|
||
|
using System.ServiceModel;
|
||
|
using System.ServiceModel.Channels;
|
||
|
using System.ServiceModel.Diagnostics;
|
||
|
using System.ServiceModel.Dispatcher;
|
||
|
using SafeCloseHandle = System.IdentityModel.SafeCloseHandle;
|
||
|
|
||
|
class ComPlusInstanceProvider : IInstanceProvider
|
||
|
{
|
||
|
ServiceInfo info;
|
||
|
static readonly Guid IID_IUnknown = new Guid("00000000-0000-0000-C000-000000000046");
|
||
|
|
||
|
public ComPlusInstanceProvider(ServiceInfo info)
|
||
|
{
|
||
|
this.info = info;
|
||
|
}
|
||
|
|
||
|
public object GetInstance(InstanceContext instanceContext)
|
||
|
{
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ComPlusInstanceProviderRequiresMessage0)));
|
||
|
}
|
||
|
|
||
|
// We call ContextUtil.IsInTransaction and ContextUtil.TransactionId, from a non-APTCA assembly. There is no identified security vulnerability with these properties,
|
||
|
// so we can't justify adding a demand for full trust here. Both properties call code marked as usafe, but no user input is passed to it and results are not
|
||
|
// cached (so there is no leak as a side-effect).
|
||
|
[SuppressMessage(FxCop.Category.Security, FxCop.Rule.AptcaMethodsShouldOnlyCallAptcaMethods)]
|
||
|
public object GetInstance(InstanceContext instanceContext, Message message)
|
||
|
{
|
||
|
|
||
|
object result = null;
|
||
|
Guid incomingTransactionID = Guid.Empty;
|
||
|
if (ContextUtil.IsInTransaction)
|
||
|
incomingTransactionID = ContextUtil.TransactionId;
|
||
|
ComPlusInstanceCreationTrace.Trace(TraceEventType.Verbose, TraceCode.ComIntegrationInstanceCreationRequest,
|
||
|
SR.TraceCodeComIntegrationInstanceCreationRequest, this.info, message, incomingTransactionID);
|
||
|
|
||
|
WindowsIdentity callerIdentity = null;
|
||
|
callerIdentity = MessageUtil.GetMessageIdentity(message);
|
||
|
WindowsImpersonationContext impersonateContext = null;
|
||
|
try
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
|
||
|
if (this.info.HostingMode ==
|
||
|
HostingMode.WebHostOutOfProcess)
|
||
|
{
|
||
|
|
||
|
if (SecurityUtils.IsAtleastImpersonationToken(new SafeCloseHandle(callerIdentity.Token, false)))
|
||
|
impersonateContext = callerIdentity.Impersonate();
|
||
|
else
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new COMException (SR.GetString(SR.BadImpersonationLevelForOutOfProcWas), HR.ERROR_BAD_IMPERSONATION_LEVEL));
|
||
|
|
||
|
}
|
||
|
|
||
|
CLSCTX clsctx = CLSCTX.SERVER;
|
||
|
if (PlatformSupportsBitness && (this.info.HostingMode ==
|
||
|
HostingMode.WebHostOutOfProcess))
|
||
|
{
|
||
|
if (this.info.Bitness == Bitness.Bitness32)
|
||
|
{
|
||
|
clsctx |= CLSCTX.ACTIVATE_32_BIT_SERVER;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
clsctx |= CLSCTX.ACTIVATE_64_BIT_SERVER;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
result = SafeNativeMethods.CoCreateInstance(
|
||
|
info.Clsid,
|
||
|
null,
|
||
|
clsctx,
|
||
|
IID_IUnknown);
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
if (impersonateContext != null)
|
||
|
impersonateContext.Undo();
|
||
|
}
|
||
|
}
|
||
|
catch (Exception e)
|
||
|
{
|
||
|
if (Fx.IsFatal(e))
|
||
|
throw;
|
||
|
|
||
|
Uri from = null;
|
||
|
if (message.Headers.From != null)
|
||
|
from = message.Headers.From.Uri;
|
||
|
|
||
|
DiagnosticUtility.EventLog.LogEvent(TraceEventType.Error,
|
||
|
(ushort)System.Runtime.Diagnostics.EventLogCategory.ComPlus,
|
||
|
(uint)System.Runtime.Diagnostics.EventLogEventId.ComPlusInstanceCreationError,
|
||
|
from == null ? string.Empty : from.ToString(),
|
||
|
this.info.AppID.ToString(),
|
||
|
this.info.Clsid.ToString(),
|
||
|
incomingTransactionID.ToString(),
|
||
|
callerIdentity.Name,
|
||
|
e.ToString());
|
||
|
|
||
|
throw TraceUtility.ThrowHelperError(e, message);
|
||
|
}
|
||
|
|
||
|
|
||
|
TransactionProxy proxy = instanceContext.Extensions.Find<TransactionProxy>();
|
||
|
if (proxy != null)
|
||
|
{
|
||
|
proxy.InstanceID = result.GetHashCode();
|
||
|
}
|
||
|
|
||
|
ComPlusInstanceCreationTrace.Trace(TraceEventType.Verbose, TraceCode.ComIntegrationInstanceCreationSuccess,
|
||
|
SR.TraceCodeComIntegrationInstanceCreationSuccess, this.info, message, result.GetHashCode(), incomingTransactionID);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
public void ReleaseInstance(InstanceContext instanceContext, object instance)
|
||
|
{
|
||
|
int instanceID = instance.GetHashCode();
|
||
|
IDisposable disposable = instance as IDisposable;
|
||
|
if (disposable != null)
|
||
|
{
|
||
|
disposable.Dispose();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// All ServicedComponents are disposable, so we don't
|
||
|
// have to worry about getting a ServicedComponent
|
||
|
// here.
|
||
|
//
|
||
|
Marshal.ReleaseComObject(instance);
|
||
|
}
|
||
|
|
||
|
ComPlusInstanceCreationTrace.Trace(TraceEventType.Verbose, TraceCode.ComIntegrationInstanceReleased,
|
||
|
SR.TraceCodeComIntegrationInstanceReleased, this.info, instanceContext, instanceID);
|
||
|
}
|
||
|
|
||
|
static bool platformSupportsBitness;
|
||
|
static bool platformSupportsBitnessSet;
|
||
|
|
||
|
static bool PlatformSupportsBitness
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
if (!platformSupportsBitnessSet)
|
||
|
{
|
||
|
// Bitness is supported on Windows 2003 Server SP1 or
|
||
|
// greater.
|
||
|
//
|
||
|
if (Environment.OSVersion.Version.Major > 5)
|
||
|
platformSupportsBitness = true;
|
||
|
else if (Environment.OSVersion.Version.Major == 5)
|
||
|
{
|
||
|
if (Environment.OSVersion.Version.Minor > 2)
|
||
|
platformSupportsBitness = true;
|
||
|
else if (Environment.OSVersion.Version.Minor == 2)
|
||
|
{
|
||
|
if (!string.IsNullOrEmpty(Environment.OSVersion.ServicePack))
|
||
|
platformSupportsBitness = true;
|
||
|
}
|
||
|
}
|
||
|
platformSupportsBitnessSet = true;
|
||
|
}
|
||
|
|
||
|
return platformSupportsBitness;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|