245 lines
9.3 KiB
C#
245 lines
9.3 KiB
C#
|
//-----------------------------------------------------------------------------
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
namespace System.ServiceModel.ComIntegration
|
||
|
{
|
||
|
using System;
|
||
|
using System.EnterpriseServices;
|
||
|
using System.IO;
|
||
|
using System.Reflection;
|
||
|
using System.Runtime;
|
||
|
using System.Runtime.InteropServices;
|
||
|
using System.ServiceModel;
|
||
|
using System.ServiceModel.Channels;
|
||
|
using System.ServiceModel.Dispatcher;
|
||
|
using System.Transactions;
|
||
|
|
||
|
class ComPlusInstanceContextInitializer : IInstanceContextInitializer
|
||
|
{
|
||
|
ServiceInfo info;
|
||
|
|
||
|
static readonly Guid IID_IServiceActivity = new Guid("67532E0C-9E2F-4450-A354-035633944E17");
|
||
|
static readonly Guid DefaultPartitionId = new Guid("41E90F3E-56C1-4633-81C3-6E8BAC8BDD70");
|
||
|
|
||
|
private static object manifestLock = new object();
|
||
|
private static string manifestFileName = Guid.NewGuid().ToString();
|
||
|
|
||
|
static ComPlusInstanceContextInitializer()
|
||
|
{
|
||
|
AppDomain currentDomain = AppDomain.CurrentDomain;
|
||
|
currentDomain.AssemblyResolve += new ResolveEventHandler(ResolveAssembly);
|
||
|
}
|
||
|
|
||
|
public ComPlusInstanceContextInitializer(ServiceInfo info)
|
||
|
{
|
||
|
this.info = info;
|
||
|
|
||
|
if (this.info.HasUdts())
|
||
|
{
|
||
|
string tempPath = String.Empty;
|
||
|
lock (manifestLock)
|
||
|
{
|
||
|
|
||
|
try
|
||
|
{
|
||
|
tempPath = Path.GetTempPath();
|
||
|
}
|
||
|
catch (Exception e)
|
||
|
{
|
||
|
if (Fx.IsFatal(e))
|
||
|
throw;
|
||
|
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(System.ServiceModel.ComIntegration.Error.CannotAccessDirectory(tempPath));
|
||
|
}
|
||
|
|
||
|
string manifestDirectory = tempPath + this.info.AppID.ToString();
|
||
|
if (Directory.Exists(manifestDirectory))
|
||
|
Directory.Delete(manifestDirectory, true);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void Initialize(InstanceContext instanceContext, Message message)
|
||
|
{
|
||
|
object serviceConfig = null;
|
||
|
serviceConfig = SetupServiceConfig(instanceContext, message);
|
||
|
|
||
|
IServiceActivity activity;
|
||
|
activity = (IServiceActivity)SafeNativeMethods.CoCreateActivity(
|
||
|
serviceConfig,
|
||
|
IID_IServiceActivity);
|
||
|
|
||
|
ComPlusSynchronizationContext syncContext;
|
||
|
bool postSynchronous = (this.info.ThreadingModel ==
|
||
|
ThreadingModel.MTA);
|
||
|
syncContext = new ComPlusSynchronizationContext(activity,
|
||
|
postSynchronous);
|
||
|
instanceContext.SynchronizationContext = syncContext;
|
||
|
|
||
|
instanceContext.Closing += this.OnInstanceContextClosing;
|
||
|
Marshal.ReleaseComObject(serviceConfig);
|
||
|
}
|
||
|
|
||
|
public void OnInstanceContextClosing(object sender, EventArgs args)
|
||
|
{
|
||
|
InstanceContext instanceContext = (InstanceContext)sender;
|
||
|
ComPlusSynchronizationContext syncContext;
|
||
|
syncContext = (ComPlusSynchronizationContext)instanceContext.SynchronizationContext;
|
||
|
syncContext.Dispose();
|
||
|
|
||
|
}
|
||
|
|
||
|
static Assembly ResolveAssembly(object sender, ResolveEventArgs args)
|
||
|
{
|
||
|
int indexOfComma = args.Name.IndexOf(",", StringComparison.Ordinal);
|
||
|
if (indexOfComma != -1)
|
||
|
{
|
||
|
Guid assemblyGuid = Guid.Empty;
|
||
|
string assemblyGuidString = args.Name.Substring(0, indexOfComma).Trim().ToLowerInvariant();
|
||
|
|
||
|
if (Guid.TryParse(assemblyGuidString, out assemblyGuid))
|
||
|
{
|
||
|
return TypeCacheManager.Provider.ResolveAssembly(assemblyGuid);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
|
||
|
object SetupServiceConfig(InstanceContext instanceContext, Message message)
|
||
|
{
|
||
|
object serviceConfig = new CServiceConfig();
|
||
|
|
||
|
// Threading
|
||
|
//
|
||
|
IServiceThreadPoolConfig threadPoolConfig;
|
||
|
threadPoolConfig = (IServiceThreadPoolConfig)(serviceConfig);
|
||
|
switch (this.info.ThreadingModel)
|
||
|
{
|
||
|
case ThreadingModel.MTA:
|
||
|
threadPoolConfig.SelectThreadPool(ThreadPoolOption.MTA);
|
||
|
break;
|
||
|
|
||
|
case ThreadingModel.STA:
|
||
|
threadPoolConfig.SelectThreadPool(ThreadPoolOption.STA);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
Fx.Assert("Unexpected threading model");
|
||
|
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.UnexpectedThreadingModel());
|
||
|
}
|
||
|
threadPoolConfig.SetBindingInfo(BindingOption.BindingToPoolThread);
|
||
|
|
||
|
// SxS activation context properties
|
||
|
//
|
||
|
|
||
|
|
||
|
// Manifest for VARIANT UDT types
|
||
|
//
|
||
|
|
||
|
// this only gets executed if we actually have UDTs
|
||
|
if (this.info.HasUdts())
|
||
|
{
|
||
|
IServiceSxsConfig sxsConfig = serviceConfig as IServiceSxsConfig;
|
||
|
if (sxsConfig == null)
|
||
|
{
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(System.ServiceModel.ComIntegration.Error.QFENotPresent());
|
||
|
}
|
||
|
|
||
|
lock (manifestLock)
|
||
|
{
|
||
|
string tempPath = String.Empty;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
tempPath = Path.GetTempPath();
|
||
|
}
|
||
|
catch (Exception e)
|
||
|
{
|
||
|
if (Fx.IsFatal(e))
|
||
|
throw;
|
||
|
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(System.ServiceModel.ComIntegration.Error.CannotAccessDirectory(tempPath));
|
||
|
}
|
||
|
|
||
|
string manifestDirectory = tempPath + this.info.AppID.ToString() + @"\";
|
||
|
|
||
|
|
||
|
if (!Directory.Exists(manifestDirectory))
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
Directory.CreateDirectory(manifestDirectory);
|
||
|
}
|
||
|
catch (Exception e)
|
||
|
{
|
||
|
if (Fx.IsFatal(e))
|
||
|
throw;
|
||
|
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(System.ServiceModel.ComIntegration.Error.CannotAccessDirectory(manifestDirectory));
|
||
|
}
|
||
|
|
||
|
Guid[] assemblyGuids = this.info.Assemblies;
|
||
|
ComIntegrationManifestGenerator.GenerateManifestCollectionFile(assemblyGuids, manifestDirectory + manifestFileName + @".manifest", manifestFileName);
|
||
|
|
||
|
foreach (Guid g in assemblyGuids)
|
||
|
{
|
||
|
Type[] types = this.info.GetTypes(g);
|
||
|
if (types.Length > 0)
|
||
|
{
|
||
|
String guidStr = g.ToString();
|
||
|
ComIntegrationManifestGenerator.GenerateWin32ManifestFile(types, manifestDirectory + guidStr + @".manifest", guidStr);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
sxsConfig.SxsConfig(CSC_SxsConfig.CSC_NewSxs);
|
||
|
sxsConfig.SxsName(manifestFileName + @".manifest");
|
||
|
sxsConfig.SxsDirectory(manifestDirectory);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// Partitions
|
||
|
//
|
||
|
if (this.info.PartitionId != DefaultPartitionId)
|
||
|
{
|
||
|
IServicePartitionConfig partitionConfig;
|
||
|
partitionConfig = (IServicePartitionConfig)(serviceConfig);
|
||
|
partitionConfig.PartitionConfig(PartitionOption.New);
|
||
|
partitionConfig.PartitionID(this.info.PartitionId);
|
||
|
}
|
||
|
|
||
|
// Transactions
|
||
|
//
|
||
|
IServiceTransactionConfig transactionConfig;
|
||
|
transactionConfig = (IServiceTransactionConfig)(serviceConfig);
|
||
|
transactionConfig.ConfigureTransaction(
|
||
|
TransactionConfig.NoTransaction);
|
||
|
|
||
|
if ((this.info.TransactionOption == TransactionOption.Required) ||
|
||
|
(this.info.TransactionOption == TransactionOption.Supported))
|
||
|
{
|
||
|
Transaction messageTransaction = null;
|
||
|
messageTransaction = MessageUtil.GetMessageTransaction(message);
|
||
|
if (messageTransaction != null)
|
||
|
{
|
||
|
TransactionProxy proxy = new TransactionProxy(info.AppID, info.Clsid);
|
||
|
proxy.SetTransaction(messageTransaction);
|
||
|
|
||
|
instanceContext.Extensions.Add(proxy);
|
||
|
IServiceSysTxnConfig sysTxnconfing = (IServiceSysTxnConfig)transactionConfig;
|
||
|
IntPtr pUnk = TransactionProxyBuilder.CreateTransactionProxyTearOff(proxy);
|
||
|
sysTxnconfing.ConfigureBYOTSysTxn(pUnk);
|
||
|
Marshal.Release(pUnk);
|
||
|
}
|
||
|
}
|
||
|
return serviceConfig;
|
||
|
}
|
||
|
}
|
||
|
}
|