The Labs \ Source Viewer \ SSCLI \ Microsoft.Vsa \ Pre

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace Microsoft.Vsa
  16. {
  17.    
  18.     using System;
  19.     using System.Collections;
  20.     using System.Diagnostics;
  21.     using System.Globalization;
  22.     using System.Reflection;
  23.     using System.Runtime.InteropServices;
  24.     using System.Security.Permissions;
  25.     using System.Threading;
  26.     using Microsoft.Win32;
  27.    
  28.     [Obsolete(Microsoft.JScript.Vsa.VsaObsolete.Description)]
  29.     [GuidAttribute("F8932A50-9127-48B6-B115-2BFDC627CEE3")]
  30.     [ComVisible(true)]
  31.     public abstract class BaseVsaEngine : IVsaEngine
  32.     {
  33.        
  34.         // === Members ===
  35.        
  36.         protected string applicationPath;
  37.         protected System.Reflection.Assembly loadedAssembly;
  38.         protected string compiledRootNamespace;
  39.         protected IVsaSite engineSite;
  40.         protected bool genDebugInfo;
  41.         protected bool haveCompiledState;
  42.         // true if there is compiled state in the engine
  43.         protected bool failedCompilation;
  44.         // true if IVsaEngine.Compile returned false on the most recent call (false by default)
  45.         protected bool isClosed;
  46.         protected bool isEngineCompiled;
  47.         // true if current compiled state reflects current source state
  48.         protected bool isDebugInfoSupported;
  49.         protected bool isEngineDirty;
  50.         // true if current source state does not reflect the persisted source state
  51.         protected bool isEngineInitialized;
  52.         protected bool isEngineRunning;
  53.         protected IVsaItems vsaItems;
  54.         protected string scriptLanguage;
  55.         protected int errorLocale;
  56.         protected static Hashtable nameTable = new Hashtable(10);
  57.         protected string engineName;
  58.         protected string engineMoniker;
  59.         protected string rootNamespace;
  60.         protected Type startupClass;
  61.         protected BaseVsaStartup startupInstance;
  62.         protected string assemblyVersion;
  63.         protected System.Security.Policy.Evidence executionEvidence;
  64.        
  65.         // === Constructor ===
  66.        
  67.         /////////////////////////////////////////////////////////////////////////////
  68.         //
  69.         // Security Issue
  70.         //
  71.         /////////////////////////////////////////////////////////////////////////////
  72.         //
  73.         // [EricLi] 12 November 2001
  74.         //
  75.         // We do not want third parties to extend BaseVsaEngine, so make the ctor
  76.         // internal. If third parties cannot extend the interface then they cannot
  77.         // access the protected members either.
  78.         //
  79.         // In vnext we should eliminate this class altogether and ship a reference
  80.         // implementation of VsaEngine as source, not binary.
  81.         //
  82.         /////////////////////////////////////////////////////////////////////////////
  83.        
  84.        
  85.         internal BaseVsaEngine(string language, string version, bool supportDebug)
  86.         {
  87.             // Set default property values and initial state
  88.             this.applicationPath = "";
  89.             this.compiledRootNamespace = null;
  90.             this.genDebugInfo = false;
  91.             this.haveCompiledState = false;
  92.             this.failedCompilation = false;
  93.             this.isClosed = false;
  94.             this.isEngineCompiled = false;
  95.             this.isEngineDirty = false;
  96.             this.isEngineInitialized = false;
  97.             this.isEngineRunning = false;
  98.             this.vsaItems = null;
  99.             this.engineSite = null;
  100.             this.errorLocale = CultureInfo.CurrentUICulture.LCID;
  101.             this.engineName = "";
  102.             this.rootNamespace = "";
  103.             this.engineMoniker = "";
  104.            
  105.             // Set implementation-dependent values
  106.             this.scriptLanguage = language;
  107.             this.assemblyVersion = version;
  108.             this.isDebugInfoSupported = supportDebug;
  109.             this.executionEvidence = null;
  110.         }
  111.        
  112.         // === Helper Methods ===
  113.        
  114.         protected VsaException Error(VsaError vsaErrorNumber)
  115.         {
  116.             return new VsaException(vsaErrorNumber);
  117.         }
  118.        
  119.         internal void TryObtainLock()
  120.         {
  121.             if (!Monitor.TryEnter(this))
  122.                 throw new VsaException(VsaError.EngineBusy);
  123.         }
  124.        
  125.         internal void ReleaseLock()
  126.         {
  127.             Monitor.Exit(this);
  128.         }
  129.        
  130.         // Pre is a set of preconditions that must hold in order to perform certain
  131.         // operations on or with the engine
  132.        
  133.         [Flags()]
  134.         protected enum Pre
  135.         {
  136.             None = 0,
  137.             EngineNotClosed = 1,
  138.             // optional; tested by default
  139.             SupportForDebug = 2,
  140.             EngineCompiled = 4,
  141.             EngineRunning = 8,
  142.             EngineNotRunning = 16,
  143.             RootMonikerSet = 32,
  144.             RootMonikerNotSet = 64,
  145.             RootNamespaceSet = 128,
  146.             SiteSet = 256,
  147.             SiteNotSet = 512,
  148.             EngineInitialised = 1024,
  149.             EngineNotInitialised = 2048
  150.         }
  151.        
  152.         private bool IsCondition(Pre flag, Pre test)
  153.         {
  154.             return ((flag & test) != Pre.None);
  155.         }
  156.        
  157.         // The Preconditions method tests a set of preconditions and throws the
  158.         // appropriate VsaException if any of them do not hold.
  159.         // Pre.EngineNotClosed is always tested, regardless of whether or not it
  160.         // appears in the flags bitfield (including when only Pre.None is indicated).
  161.        
  162.         protected void Preconditions(Pre flags)
  163.         {
  164.             // Every operation on this object requires that the engine not be closed
  165.             if (this.isClosed)
  166.                 throw Error(VsaError.EngineClosed);
  167.             if (flags == (Pre.EngineNotClosed | Pre.None))
  168.                 return;
  169.            
  170.             if (IsCondition(flags, Pre.SupportForDebug) && !this.isDebugInfoSupported)
  171.                 throw Error(VsaError.DebugInfoNotSupported);
  172.             if (IsCondition(flags, Pre.EngineCompiled) && !this.haveCompiledState)
  173.                 throw Error(VsaError.EngineNotCompiled);
  174.             if (IsCondition(flags, Pre.EngineRunning) && !this.isEngineRunning)
  175.                 throw Error(VsaError.EngineNotRunning);
  176.             if (IsCondition(flags, Pre.EngineNotRunning) && this.isEngineRunning)
  177.                 throw Error(VsaError.EngineRunning);
  178.             if (IsCondition(flags, Pre.RootMonikerSet) && (this.engineMoniker == ""))
  179.                 throw Error(VsaError.RootMonikerNotSet);
  180.             if (IsCondition(flags, Pre.RootMonikerNotSet) && (this.engineMoniker != ""))
  181.                 throw Error(VsaError.RootMonikerAlreadySet);
  182.             if (IsCondition(flags, Pre.RootNamespaceSet) && (this.rootNamespace == ""))
  183.                 throw Error(VsaError.RootNamespaceNotSet);
  184.             if (IsCondition(flags, Pre.SiteSet) && (this.engineSite == null))
  185.                 throw Error(VsaError.SiteNotSet);
  186.             if (IsCondition(flags, Pre.SiteNotSet) && (this.engineSite != null))
  187.                 throw Error(VsaError.SiteAlreadySet);
  188.             if (IsCondition(flags, Pre.EngineInitialised) && !this.isEngineInitialized)
  189.                 throw Error(VsaError.EngineNotInitialized);
  190.             if (IsCondition(flags, Pre.EngineNotInitialised) && this.isEngineInitialized)
  191.                 throw Error(VsaError.EngineInitialized);
  192.         }
  193.        
  194.         // === Properties ===
  195.        
  196.         // IVsaEngine.AppDomain is not supported by managed engines
  197.         public System._AppDomain AppDomain {
  198.             get {
  199.                 Preconditions(Pre.EngineNotClosed);
  200.                 throw new NotSupportedException();
  201.             }
  202.             set {
  203.                 Preconditions(Pre.EngineNotClosed);
  204.                 throw new VsaException(VsaError.AppDomainCannotBeSet);
  205.             }
  206.         }
  207.        
  208.        
  209.         /////////////////////////////////////////////////////////////////////////////
  210.         //
  211.         // Security Issue
  212.         //
  213.         /////////////////////////////////////////////////////////////////////////////
  214.         //
  215.         // [EricLi] 13 November 2001
  216.         //
  217.         // The Evidence property must demand permission to control evidence
  218.         // on both read and write. On write because an untrusted caller
  219.         // could attempt to set the evidence to null, thereby causing the
  220.         // emitted assembly to use Microsoft.JScript.DLL's evidence, granting
  221.         // full trust. On read because an untrusted assembly could
  222.         // mutate it or derive information from it.
  223.         //
  224.         /////////////////////////////////////////////////////////////////////////////
  225.        
  226.         public System.Security.Policy.Evidence Evidence {
  227.             [SecurityPermission(SecurityAction.Demand, ControlEvidence = true)]
  228.             [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  229.             get {
  230.                 Preconditions(Pre.EngineNotClosed | Pre.EngineInitialised);
  231.                 return this.executionEvidence;
  232.             }
  233.             [SecurityPermission(SecurityAction.Demand, ControlEvidence = true)]
  234.             [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  235.             set {
  236.                 Preconditions(Pre.EngineNotClosed | Pre.EngineNotRunning | Pre.EngineInitialised);
  237.                 this.executionEvidence = value;
  238.             }
  239.         }
  240.        
  241.         // IVsaEngine.ApplicationBase is not supported by managed engines
  242.         public string ApplicationBase {
  243.             get {
  244.                 Preconditions(Pre.EngineNotClosed);
  245.                 throw new NotSupportedException();
  246.             }
  247.             set {
  248.                 Preconditions(Pre.EngineNotClosed);
  249.                 throw new VsaException(VsaError.ApplicationBaseCannotBeSet);
  250.             }
  251.         }
  252.        
  253.         public System.Reflection.Assembly Assembly {
  254.             get {
  255.                 Preconditions(Pre.EngineNotClosed | Pre.EngineRunning);
  256.                 return this.loadedAssembly;
  257.             }
  258.         }
  259.        
  260.         public bool GenerateDebugInfo {
  261.             [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  262.             get {
  263.                 Preconditions(Pre.EngineNotClosed | Pre.EngineInitialised);
  264.                 return this.genDebugInfo;
  265.             }
  266.             [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  267.             set {
  268.                 this.TryObtainLock();
  269.                 try {
  270.                     Preconditions(Pre.EngineNotClosed | Pre.EngineNotRunning | Pre.EngineInitialised | Pre.SupportForDebug);
  271.                     if (this.genDebugInfo != value) {
  272.                         this.genDebugInfo = value;
  273.                         this.isEngineDirty = true;
  274.                         this.isEngineCompiled = false;
  275.                     }
  276.                 }
  277.                 finally {
  278.                     this.ReleaseLock();
  279.                 }
  280.             }
  281.         }
  282.        
  283.         public bool IsCompiled {
  284.             [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  285.             get {
  286.                 Preconditions(Pre.EngineNotClosed | Pre.EngineInitialised);
  287.                 return this.isEngineCompiled;
  288.             }
  289.         }
  290.        
  291.         public bool IsDirty {
  292.             [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  293.             get {
  294.                 Preconditions(Pre.EngineNotClosed | Pre.EngineInitialised);
  295.                 return this.isEngineDirty;
  296.             }
  297.             // IsDirty setter is used by VsaItems to notify the engine when new items have been
  298.             // manipulated or added to/removed from the engine. It is not part of an interface.
  299.             [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  300.             set {
  301.                 this.TryObtainLock();
  302.                 try {
  303.                     Preconditions(Pre.EngineNotClosed);
  304.                     this.isEngineDirty = value;
  305.                     if (this.isEngineDirty)
  306.                         this.isEngineCompiled = false;
  307.                 }
  308.                 finally {
  309.                     this.ReleaseLock();
  310.                 }
  311.             }
  312.         }
  313.        
  314.         public bool IsRunning {
  315.             [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  316.             get {
  317.                 Preconditions(Pre.EngineNotClosed | Pre.EngineInitialised);
  318.                 return this.isEngineRunning;
  319.             }
  320.         }
  321.        
  322.         public IVsaItems Items {
  323.             [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  324.             get {
  325.                 Preconditions(Pre.EngineNotClosed | Pre.EngineInitialised);
  326.                 return this.vsaItems;
  327.             }
  328.         }
  329.        
  330.         public string Language {
  331.             [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  332.             get {
  333.                 Preconditions(Pre.EngineNotClosed | Pre.EngineInitialised);
  334.                 return this.scriptLanguage;
  335.             }
  336.         }
  337.        
  338.         public int LCID {
  339.             [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  340.             get {
  341.                 Preconditions(Pre.EngineNotClosed | Pre.EngineInitialised);
  342.                 return this.errorLocale;
  343.             }
  344.             [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  345.             set {
  346.                 this.TryObtainLock();
  347.                 try {
  348.                     Preconditions(Pre.EngineNotClosed | Pre.EngineInitialised | Pre.EngineNotRunning);
  349.                     try {
  350.                         CultureInfo errorCultureInfo = new CultureInfo(value);
  351.                     }
  352.                     catch (ArgumentException) {
  353.                         throw Error(VsaError.LCIDNotSupported);
  354.                     }
  355.                     this.errorLocale = value;
  356.                     this.isEngineDirty = true;
  357.                 }
  358.                 finally {
  359.                     this.ReleaseLock();
  360.                 }
  361.             }
  362.         }
  363.        
  364.         public string Name {
  365.             [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  366.             get {
  367.                 Preconditions(Pre.EngineNotClosed | Pre.EngineInitialised);
  368.                 return this.engineName;
  369.             }
  370.             [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  371.             set {
  372.                 this.TryObtainLock();
  373.                 try {
  374.                     Preconditions(Pre.EngineNotClosed | Pre.EngineNotRunning | Pre.EngineInitialised);
  375.                     // if the new name is the same as the old one, do nothing
  376.                     if (this.engineName == value)
  377.                         return;
  378.                     // put the name into a static table so that we can detect duplicates
  379.                     lock (nameTable) {
  380.                         if (nameTable[value] != null)
  381.                             throw Error(VsaError.EngineNameInUse);
  382.                         nameTable[value] = new object();
  383.                         if (this.engineName != null && this.engineName.Length > 0)
  384.                             nameTable[this.engineName] = null;
  385.                     }
  386.                     this.engineName = value;
  387.                     this.isEngineDirty = true;
  388.                     this.isEngineCompiled = false;
  389.                 }
  390.                 finally {
  391.                     this.ReleaseLock();
  392.                 }
  393.             }
  394.         }
  395.        
  396.         public string RootMoniker {
  397.             [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  398.             get {
  399.                 Preconditions(Pre.EngineNotClosed);
  400.                 return this.engineMoniker;
  401.             }
  402.             [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  403.             set {
  404.                 this.TryObtainLock();
  405.                 try {
  406.                     Preconditions(Pre.EngineNotClosed | Pre.RootMonikerNotSet);
  407.                     this.ValidateRootMoniker(value);
  408.                     this.engineMoniker = value;
  409.                 }
  410.                 finally {
  411.                     this.ReleaseLock();
  412.                 }
  413.             }
  414.         }
  415.        
  416.         public string RootNamespace {
  417.             [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  418.             get {
  419.                 Preconditions(Pre.EngineNotClosed | Pre.EngineInitialised);
  420.                 return this.rootNamespace;
  421.             }
  422.             [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  423.             set {
  424.                 this.TryObtainLock();
  425.                 try {
  426.                     Preconditions(Pre.EngineNotClosed | Pre.EngineNotRunning | Pre.EngineInitialised);
  427.                     if (!IsValidNamespaceName(value))
  428.                         throw Error(VsaError.RootNamespaceInvalid);
  429.                     this.rootNamespace = value;
  430.                     this.isEngineDirty = true;
  431.                     this.isEngineCompiled = false;
  432.                 }
  433.                 finally {
  434.                     this.ReleaseLock();
  435.                 }
  436.             }
  437.         }
  438.        
  439.         public IVsaSite Site {
  440.             [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  441.             get {
  442.                 Preconditions(Pre.EngineNotClosed | Pre.RootMonikerSet);
  443.                 return this.engineSite;
  444.             }
  445.             [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  446.             set {
  447.                 this.TryObtainLock();
  448.                 try {
  449.                     Preconditions(Pre.EngineNotClosed | Pre.RootMonikerSet | Pre.SiteNotSet);
  450.                     if (value == null)
  451.                         throw Error(VsaError.SiteInvalid);
  452.                     this.engineSite = value;
  453.                 }
  454.                 finally {
  455.                     this.ReleaseLock();
  456.                 }
  457.             }
  458.         }
  459.        
  460.         public string Version {
  461.             [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  462.             get {
  463.                 Preconditions(Pre.EngineNotClosed | Pre.EngineInitialised);
  464.                 return this.assemblyVersion;
  465.             }
  466.         }
  467.        
  468.         // === Methods ===
  469.        
  470.         [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  471.         public virtual void Close()
  472.         {
  473.             this.TryObtainLock();
  474.             try {
  475.                 Preconditions(Pre.EngineNotClosed);
  476.                 if (this.isEngineRunning)
  477.                     this.Reset();
  478.                 lock (nameTable) {
  479.                     if (this.engineName != null && this.engineName.Length > 0)
  480.                         nameTable[this.engineName] = null;
  481.                 }
  482.                 this.DoClose();
  483.                 this.isClosed = true;
  484.             }
  485.             finally {
  486.                 this.ReleaseLock();
  487.             }
  488.         }
  489.        
  490.         // See security comment at Run()
  491.         [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  492.         [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  493.         public virtual bool Compile()
  494.         {
  495.             this.TryObtainLock();
  496.             try {
  497.                 Preconditions(Pre.EngineNotClosed | Pre.EngineNotRunning | Pre.EngineInitialised | Pre.RootNamespaceSet);
  498.                 // look through items for at least one code item
  499.                 bool haveCode = false;
  500.                 for (int i = 0int n = this.vsaItems.Count; !haveCode && i < n; ++i) {
  501.                     IVsaItem item = vsaItems[i];
  502.                     haveCode = this.vsaItems[i].ItemType == VsaItemType.Code;
  503.                 }
  504.                 if (!haveCode)
  505.                     throw Error(VsaError.EngineEmpty);
  506.                 try {
  507.                     this.ResetCompiledState();
  508.                     this.isEngineCompiled = DoCompile();
  509.                 }
  510.                 catch (VsaException) {
  511.                     throw;
  512.                 }
  513.                 catch (Exception e) {
  514.                     throw new VsaException(VsaError.InternalCompilerError, e.ToString(), e);
  515.                 }
  516.                 catch {
  517.                     throw new VsaException(VsaError.InternalCompilerError);
  518.                 }
  519.                 if (this.isEngineCompiled) {
  520.                     this.haveCompiledState = true;
  521.                     this.failedCompilation = false;
  522.                     this.compiledRootNamespace = this.rootNamespace;
  523.                 }
  524.                 return this.isEngineCompiled;
  525.             }
  526.             finally {
  527.                 this.ReleaseLock();
  528.             }
  529.         }
  530.        
  531.         [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  532.         public virtual object GetOption(string name)
  533.         {
  534.             this.TryObtainLock();
  535.             try {
  536.                 Preconditions(Pre.EngineNotClosed | Pre.EngineInitialised);
  537.                 object option = GetCustomOption(name);
  538.                 return option;
  539.             }
  540.             finally {
  541.                 this.ReleaseLock();
  542.             }
  543.         }
  544.        
  545.         [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  546.         public virtual void InitNew()
  547.         {
  548.             this.TryObtainLock();
  549.             try {
  550.                 Preconditions(Pre.EngineNotClosed | Pre.EngineNotInitialised | Pre.RootMonikerSet | Pre.SiteSet);
  551.                 this.isEngineInitialized = true;
  552.             }
  553.             finally {
  554.                 this.ReleaseLock();
  555.             }
  556.         }
  557.        
  558.         // Load the local compiled state into the AppDomain and return the loaded assembly
  559.         protected virtual Assembly LoadCompiledState()
  560.         {
  561.             Debug.Assert(this.haveCompiledState);
  562.             byte[] pe;
  563.             byte[] pdb;
  564.             this.DoSaveCompiledState(out pe, out pdb);
  565.             return Assembly.Load(pe, pdb, this.executionEvidence);
  566.         }
  567.        
  568.         [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  569.         public virtual void LoadSourceState(IVsaPersistSite site)
  570.         {
  571.             this.TryObtainLock();
  572.             try {
  573.                 Preconditions(Pre.EngineNotClosed | Pre.EngineNotInitialised | Pre.RootMonikerSet | Pre.SiteSet);
  574.                 this.isEngineInitialized = true;
  575.                 try {
  576.                     this.DoLoadSourceState(site);
  577.                 }
  578.                 catch {
  579.                     this.isEngineInitialized = false;
  580.                     throw;
  581.                 }
  582.                 this.isEngineDirty = false;
  583.             }
  584.             finally {
  585.                 this.ReleaseLock();
  586.             }
  587.         }
  588.        
  589.         [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  590.         public virtual void Reset()
  591.         {
  592.             this.TryObtainLock();
  593.             try {
  594.                 Preconditions(Pre.EngineNotClosed | Pre.EngineRunning);
  595.                 try {
  596.                     this.startupInstance.Shutdown();
  597.                 }
  598.                 catch (Exception e) {
  599.                     throw new VsaException(VsaError.EngineCannotReset, e.ToString(), e);
  600.                 }
  601.                 catch {
  602.                     throw new VsaException(VsaError.EngineCannotReset);
  603.                 }
  604.                 this.isEngineRunning = false;
  605.                 this.loadedAssembly = null;
  606.             }
  607.             finally {
  608.                 this.ReleaseLock();
  609.             }
  610.         }
  611.        
  612.         [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  613.         public virtual void RevokeCache()
  614.         {
  615.             this.TryObtainLock();
  616.             try {
  617.                 Preconditions(Pre.EngineNotClosed | Pre.EngineNotRunning | Pre.RootMonikerSet);
  618.                 try {
  619.                     System.AppDomain.CurrentDomain.SetData(this.engineMoniker, null);
  620.                 }
  621.                 catch (Exception e) {
  622.                     throw new VsaException(VsaError.RevokeFailed, e.ToString(), e);
  623.                 }
  624.                 catch {
  625.                     throw new VsaException(VsaError.RevokeFailed);
  626.                 }
  627.             }
  628.             finally {
  629.                 this.ReleaseLock();
  630.             }
  631.         }
  632.        
  633.         /////////////////////////////////////////////////////////////////////////////
  634.         //
  635.         // Security Issue
  636.         //
  637.         /////////////////////////////////////////////////////////////////////////////
  638.         //
  639.         // [EricLi] 10 November 2001
  640.         //
  641.         // Right now the BaseVsa class requires full trust to use as
  642.         // an engine that runs code or generates assemblies.
  643.         //
  644.         // Preventing untrusted callers from actually compiling and
  645.         // running code is clearly undesirable -- we want partially-
  646.         // trusted host scenarios to work. For this release however
  647.         // there are too many poorly-understood issues involving
  648.         // controling the evidence property.
  649.         //
  650.         /////////////////////////////////////////////////////////////////////////////
  651.        
  652.         [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  653.         [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  654.         public virtual void Run()
  655.         {
  656.             this.TryObtainLock();
  657.             try {
  658.                 Preconditions(Pre.EngineNotClosed | Pre.EngineNotRunning | Pre.RootMonikerSet | Pre.SiteSet | Pre.RootNamespaceSet);
  659.                 // managed engines cannot support the AppDomain property so we always use the current one
  660.                 AppDomain appDomain = System.AppDomain.CurrentDomain;
  661.                 if (this.haveCompiledState) {
  662.                     // make sure the RootNamespace hasn't been changed since the compilation
  663.                     if (this.rootNamespace != this.compiledRootNamespace)
  664.                         throw new VsaException(VsaError.RootNamespaceInvalid);
  665.                     this.loadedAssembly = this.LoadCompiledState();
  666.                     appDomain.SetData(this.engineMoniker, this.loadedAssembly);
  667.                 }
  668.                 else {
  669.                     // if Compile returned false last time it was called, quit before cache lookup or callback
  670.                     if (this.failedCompilation)
  671.                         throw new VsaException(VsaError.EngineNotCompiled);
  672.                     this.startupClass = null;
  673.                     this.loadedAssembly = appDomain.GetData(this.engineMoniker) as Assembly;
  674.                     if (this.loadedAssembly == null) {
  675.                         // assembly is not in the cache, so callback to the site for compiled state
  676.                         // prevent multiple callbacks which could result in duplicate assemblies being loaded into the AppDomain
  677.                         string mutexName = this.engineMoniker + "/" + appDomain.GetHashCode().ToString(CultureInfo.InvariantCulture);
  678.                         Mutex compiledStateCallbackMutex = new Mutex(false, mutexName);
  679.                         if (compiledStateCallbackMutex.WaitOne()) {
  680.                             try {
  681.                                 // see if there was another callback before we got the lock
  682.                                 this.loadedAssembly = appDomain.GetData(this.engineMoniker) as Assembly;
  683.                                 if (this.loadedAssembly == null) {
  684.                                     byte[] pe;
  685.                                     byte[] pdb;
  686.                                     this.engineSite.GetCompiledState(out pe, out pdb);
  687.                                     if (pe == null)
  688.                                         throw new VsaException(VsaError.GetCompiledStateFailed);
  689.                                     this.loadedAssembly = Assembly.Load(pe, pdb, this.executionEvidence);
  690.                                     appDomain.SetData(this.engineMoniker, this.loadedAssembly);
  691.                                 }
  692.                             }
  693.                             finally {
  694.                                 compiledStateCallbackMutex.ReleaseMutex();
  695.                                 compiledStateCallbackMutex.Close();
  696.                             }
  697.                         }
  698.                     }
  699.                 }
  700.                 // update the _Startup class Type object (if needed)
  701.                 try {
  702.                     if (this.startupClass == null)
  703.                         this.startupClass = this.loadedAssembly.GetType(this.rootNamespace + "._Startup", true);
  704.                 }
  705.                 catch (Exception e) {
  706.                     // the _Startup class was not in the RootNamespace
  707.                     throw new VsaException(VsaError.BadAssembly, e.ToString(), e);
  708.                 }
  709.                 catch {
  710.                     // the _Startup class was not in the RootNamespace
  711.                     throw new VsaException(VsaError.BadAssembly);
  712.                 }
  713.                 // set the engine to running, callback for global and event instances, then run global code
  714.                 try {
  715.                     this.startupInstance = (BaseVsaStartup)Activator.CreateInstance(this.startupClass);
  716.                     this.isEngineRunning = true;
  717.                     this.startupInstance.SetSite(this.engineSite);
  718.                     this.startupInstance.Startup();
  719.                 }
  720.                 catch (Exception e) {
  721.                     throw new VsaException(VsaError.UnknownError, e.ToString(), e);
  722.                 }
  723.                 catch {
  724.                     throw new VsaException(VsaError.UnknownError);
  725.                 }
  726.             }
  727.             finally {
  728.                 this.ReleaseLock();
  729.             }
  730.         }
  731.        
  732.         [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  733.         public virtual void SetOption(string name, object value)
  734.         {
  735.             this.TryObtainLock();
  736.             try {
  737.                 Preconditions(Pre.EngineNotClosed | Pre.EngineNotRunning | Pre.EngineInitialised);
  738.                 this.SetCustomOption(name, value);
  739.             }
  740.             finally {
  741.                 this.ReleaseLock();
  742.             }
  743.         }
  744.        
  745.         [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  746.         public virtual void SaveCompiledState(out byte[] pe, out byte[] debugInfo)
  747.         {
  748.             this.TryObtainLock();
  749.             try {
  750.                 Preconditions(Pre.EngineNotClosed | Pre.EngineNotRunning | Pre.EngineCompiled | Pre.EngineInitialised);
  751.                 this.DoSaveCompiledState(out pe, out debugInfo);
  752.             }
  753.             finally {
  754.                 this.ReleaseLock();
  755.             }
  756.         }
  757.        
  758.         [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  759.         public virtual void SaveSourceState(IVsaPersistSite site)
  760.         {
  761.             this.TryObtainLock();
  762.             try {
  763.                 Preconditions(Pre.EngineNotClosed | Pre.EngineNotRunning | Pre.EngineInitialised);
  764.                 if (site == null)
  765.                     throw Error(VsaError.SiteInvalid);
  766.                 try {
  767.                     DoSaveSourceState(site);
  768.                 }
  769.                 catch (Exception e) {
  770.                     throw new VsaException(VsaError.SaveElementFailed, e.ToString(), e);
  771.                 }
  772.                 catch {
  773.                     throw new VsaException(VsaError.SaveElementFailed);
  774.                 }
  775.             }
  776.             finally {
  777.                 this.ReleaseLock();
  778.             }
  779.         }
  780.        
  781.         protected virtual void ValidateRootMoniker(string rootMoniker)
  782.         {
  783.             // Refer to RFC 2396 for details: ftp://nis.nsf.net/internet/documents/rfc/rfc2396.txt
  784.             if (rootMoniker == null)
  785.                 throw new VsaException(VsaError.RootMonikerInvalid);
  786.             Uri moniker = null;
  787.             try {
  788.                 moniker = new Uri(rootMoniker);
  789.             }
  790.             catch (UriFormatException) {
  791.                 throw new VsaException(VsaError.RootMonikerInvalid);
  792.             }
  793.             // The overall format is okay, so now we validate the protocol
  794.             string protocol = moniker.Scheme;
  795.             if (protocol.Length == 0)
  796.                 throw new VsaException(VsaError.RootMonikerProtocolInvalid);
  797.             string[] knownSchemes = {"file", "ftp", "gopher", "http", "https", "javascript", "mailto", "microsoft", "news", "res",
  798.             "smtp", "socks", "vbscript", "xlang", "xml", "xpath", "xsd", "xsl"};
  799.             foreach (string scheme in knownSchemes) {
  800.                 // Scheme names are case-insensitive (RFC 2396 section 3.2)
  801.                 if (String.Compare(scheme, protocol, StringComparison.OrdinalIgnoreCase) == 0)
  802.                     throw new VsaException(VsaError.RootMonikerProtocolInvalid);
  803.             }
  804.         }
  805.        
  806.         // === Abstract Methods ===
  807.        
  808.         // Implement this method to clean up data structures
  809.         protected abstract void DoClose();
  810.        
  811.         // Return flag for compilation success.
  812.         // Errors should be reported to the engine site via OnCompilerError.
  813.         // Internal compiler errors should throw exceptions.
  814.         protected abstract bool DoCompile();
  815.        
  816.         // Implement this method to load source state from site
  817.         protected abstract void DoLoadSourceState(IVsaPersistSite site);
  818.        
  819.         protected abstract void DoSaveCompiledState(out byte[] pe, out byte[] debugInfo);
  820.        
  821.         // Save source items using IVsaPersistSite.SaveElement
  822.         protected abstract void DoSaveSourceState(IVsaPersistSite site);
  823.        
  824.         // Enable custom options
  825.         protected abstract object GetCustomOption(string name);
  826.        
  827.         // Verify that the name is a valid namespace name
  828.         protected abstract bool IsValidNamespaceName(string name);
  829.        
  830.         // Verify that the identifier is valid for the language
  831.         [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  832.         public abstract bool IsValidIdentifier(string ident);
  833.        
  834.         // Discard the existing compiled state so we can compile a new source state
  835.         // Postconditions:
  836.         // this.haveCompiledState == false
  837.         // this.failedCompilation == true
  838.         // this.compiledRootNamespace == null
  839.         // this.startupClass == null
  840.         protected abstract void ResetCompiledState();
  841.        
  842.         // Enable custom options
  843.         protected abstract void SetCustomOption(string name, object value);
  844.     }
  845.    
  846.     // BaseVsaSite is a default implementation of IVsaSite. Note that GetCompiledState
  847.     // defers to two properties so that languages that don't support declaring out params
  848.     // can provide an implementation without having to change languages.
  849.    
  850.     [Obsolete(Microsoft.JScript.Vsa.VsaObsolete.Description)]
  851.     public class BaseVsaSite : IVsaSite
  852.     {
  853.         public virtual byte[] Assembly {
  854.             get {
  855.                 throw new VsaException(VsaError.GetCompiledStateFailed);
  856.             }
  857.         }
  858.        
  859.         public virtual byte[] DebugInfo {
  860.             get { return null; }
  861.         }
  862.        
  863.         [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  864.         public virtual void GetCompiledState(out byte[] pe, out byte[] debugInfo)
  865.         {
  866.             pe = this.Assembly;
  867.             debugInfo = this.DebugInfo;
  868.         }
  869.        
  870.         public virtual object GetEventSourceInstance(string itemName, string eventSourceName)
  871.         {
  872.             throw new VsaException(VsaError.CallbackUnexpected);
  873.         }
  874.        
  875.         public virtual object GetGlobalInstance(string name)
  876.         {
  877.             throw new VsaException(VsaError.CallbackUnexpected);
  878.         }
  879.        
  880.         [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  881.         public virtual void Notify(string notify, object optional)
  882.         {
  883.             throw new VsaException(VsaError.CallbackUnexpected);
  884.         }
  885.        
  886.         [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  887.         public virtual bool OnCompilerError(IVsaError error)
  888.         {
  889.             return false;
  890.         }
  891.     }
  892.    
  893.     [Obsolete(Microsoft.JScript.Vsa.VsaObsolete.Description)]
  894.     public abstract class BaseVsaStartup
  895.     {
  896.         protected IVsaSite site;
  897.         public void SetSite(IVsaSite site)
  898.         {
  899.             this.site = site;
  900.         }
  901.         public abstract void Startup();
  902.         public abstract void Shutdown();
  903.     }
  904. }

Developer Fusion