| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace System.ServiceModel.ComIntegration
- {
- using System;
- using System.Collections.Generic;
- using System.Diagnostics.CodeAnalysis;
- using System.EnterpriseServices;
- using System.Runtime.InteropServices;
- using System.ServiceModel.Configuration;
- using System.Diagnostics;
- using System.Runtime;
- using System.Runtime.Diagnostics;
- using System.Threading;
- using System.ServiceModel.Diagnostics;
- class DllHostInitializeWorker
- {
- List<ComPlusServiceHost> hosts = new List<ComPlusServiceHost>();
- Guid applicationId;
- // This thread pings rpcss and the host process so that
- // it does not assume that we are stuck and kills itself.
- [SuppressMessage(FxCop.Category.Security, FxCop.Rule.AptcaMethodsShouldOnlyCallAptcaMethods)] // no identified security vulnerability that would justify making a breaking change
- public static void PingProc(object o)
- {
- IProcessInitControl control = o as IProcessInitControl;
- try
- {
- // This will loop for a max of 2000 seconds, which is a sanity check
- // that should never be hit. The assumption behind that is that
- // the main thread will not get stuck. It will either make progress
- // or fail with an exception, which will abort this thread and kill the process.
- // No COM app should take longer than 30 minutes to initialize since an app that
- // takes that long would have to be so big that it hits other limits before it hits this.
- for (int i = 0; i < 200; i++)
- {
- Thread.Sleep(10000);
- // Add 30 more seconds to the timeout
- control.ResetInitializerTimeout(30);
- }
- }
- catch (ThreadAbortException)
- {
- }
- }
- // We call ContextUtil.ApplicationId, from a non-APTCA assembly. There is no identified security vulnerability with that property, so we can't justify
- // adding a demand for full trust here, causing a breaking change to the public DllHostInitializer.Startup(..) method that calls this one.
- // ContextUtil.ApplicationId calls a native function (GetObjectContext from mtxex.dll), but it doesn't pass user input to it, and it doesn't
- // cache its result (so there is no leak as a side-effect).
- [SuppressMessage(FxCop.Category.Security, FxCop.Rule.AptcaMethodsShouldOnlyCallAptcaMethods)]
- public void Startup(IProcessInitControl control)
- {
- // Find our application object, and associated components
- // (classes) collection from the COM+ catalog.
- //
- applicationId = ContextUtil.ApplicationId;
- ComPlusDllHostInitializerTrace.Trace(TraceEventType.Information, TraceCode.ComIntegrationDllHostInitializerStarting,
- SR.TraceCodeComIntegrationDllHostInitializerStarting, applicationId);
- Thread pingThread = null;
- try
- {
- pingThread = new Thread(PingProc);
- pingThread.Start(control);
- ComCatalogObject application;
- application = CatalogUtil.FindApplication(applicationId);
- if (application == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ListenerInitFailed(
- SR.GetString(SR.ApplicationNotFound,
- applicationId.ToString("B").ToUpperInvariant())));
- }
- bool processPooled = ((int)application.GetValue("ConcurrentApps")) > 1;
- if (processPooled)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ListenerInitFailed(
- SR.GetString(SR.PooledApplicationNotSupportedForComplusHostedScenarios,
- applicationId.ToString("B").ToUpperInvariant())));
- }
- bool processRecycled = ((int)application.GetValue("RecycleLifetimeLimit")) > 0 ||
- ((int)application.GetValue("RecycleCallLimit")) > 0 ||
- ((int)application.GetValue("RecycleActivationLimit")) > 0 ||
- ((int)application.GetValue("RecycleMemoryLimit")) > 0;
- if (processRecycled)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ListenerInitFailed(
- SR.GetString(SR.RecycledApplicationNotSupportedForComplusHostedScenarios,
- applicationId.ToString("B").ToUpperInvariant())));
- }
- ComCatalogCollection classes;
- classes = application.GetCollection("Components");
- // Load up Indigo configuration.
- //
- ServicesSection services = ServicesSection.GetSection();
- bool foundService = false;
- foreach (ServiceElement service in services.Services)
- {
- Guid clsidToCompare = Guid.Empty;
- Guid appIdToCompare = Guid.Empty;
- string[] serviceParams = service.Name.Split(',');
- if (serviceParams.Length != 2)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.OnlyClsidsAllowedForServiceType, service.Name)));
- }
- if (!DiagnosticUtility.Utility.TryCreateGuid(serviceParams[0], out appIdToCompare))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.OnlyClsidsAllowedForServiceType, service.Name)));
- }
- if (!DiagnosticUtility.Utility.TryCreateGuid(serviceParams[1], out clsidToCompare))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.OnlyClsidsAllowedForServiceType, service.Name)));
- }
- foundService = false;
- // CODEWORK: Consider farming this out across multiple threadpool threads.
- // When it was discovered that startup time could be a problem it was too late
- // to to do that since it can cause failure conditions that need to be considered
- // (such as the threadpool running out) so we decided not to touch that part.
- // But since this can potentially take a very long time on big COM apps
- // it should be parallelized at some point.
- foreach (ComCatalogObject classObject in classes)
- {
- Guid clsid = Fx.CreateGuid((string)classObject.GetValue("CLSID"));
- if (clsid == clsidToCompare && applicationId == appIdToCompare)
- {
- foundService = true;
- ComPlusDllHostInitializerTrace.Trace(TraceEventType.Verbose, TraceCode.ComIntegrationDllHostInitializerAddingHost,
- SR.TraceCodeComIntegrationDllHostInitializerAddingHost, applicationId, clsid, service);
- this.hosts.Add(
- new DllHostedComPlusServiceHost(clsid,
- service,
- application,
- classObject));
- }
- }
- if (!foundService)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString
- (SR.CannotFindClsidInApplication, clsidToCompare.ToString("B").ToUpperInvariant(), applicationId.ToString("B").ToUpperInvariant())));
- }
- if (foundService == false)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.DllHostInitializerFoundNoServices());
- }
- foreach (ComPlusServiceHost host in this.hosts)
- {
- host.Open();
- }
- }
- catch (Exception e)
- {
- DiagnosticUtility.EventLog.LogEvent(TraceEventType.Error,
- (ushort)System.Runtime.Diagnostics.EventLogCategory.ComPlus,
- (uint)System.Runtime.Diagnostics.EventLogEventId.ComPlusDllHostInitializerStartingError,
- applicationId.ToString(),
- e.ToString());
- throw;
- }
- finally
- {
- if (null != pingThread)
- pingThread.Abort(); // We are done; stop pinging.
- }
- ComPlusDllHostInitializerTrace.Trace(TraceEventType.Information, TraceCode.ComIntegrationDllHostInitializerStarted,
- SR.TraceCodeComIntegrationDllHostInitializerStarted, applicationId);
- }
- public void Shutdown()
- {
- ComPlusDllHostInitializerTrace.Trace(TraceEventType.Information, TraceCode.ComIntegrationDllHostInitializerStopping,
- SR.TraceCodeComIntegrationDllHostInitializerStopping, applicationId);
- foreach (ComPlusServiceHost host in this.hosts)
- {
- host.Close();
- }
- ComPlusDllHostInitializerTrace.Trace(TraceEventType.Information, TraceCode.ComIntegrationDllHostInitializerStopped,
- SR.TraceCodeComIntegrationDllHostInitializerStopped, applicationId);
- }
- }
- [ComVisible(true)]
- [Guid("59856830-3ECB-4D29-9CFE-DDD0F74B96A2")]
- public class DllHostInitializer : IProcessInitializer
- {
- DllHostInitializeWorker worker = new DllHostInitializeWorker();
- public void Startup(object punkProcessControl)
- {
- IProcessInitControl control = punkProcessControl as IProcessInitControl;
- worker.Startup(control);
- }
- public void Shutdown()
- {
- worker.Shutdown();
- }
- }
- }
|