Merge pull request #1502 from madrang/SafeHandle.CloseTestDispose
[mono.git] / mcs / class / System.Web / System.Web / HttpRuntime.cs
1 //
2 // System.Web.HttpRuntime.cs 
3 // 
4 // Authors:
5 //      Miguel de Icaza (miguel@novell.com)
6 //      Marek Habersack <mhabersack@novell.com>
7 //
8 //
9 // Copyright (C) 2005-2010 Novell, Inc (http://www.novell.com)
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 //
32 // TODO: Call HttpRequest.CloseInputStream when we finish a request, as we are using the IntPtr stream.
33 //
34 using System.IO;
35 using System.Text;
36 using System.Globalization;
37 using System.Collections;
38 using System.Collections.Concurrent;
39 using System.Reflection;
40 using System.Security;
41 using System.Security.Permissions;
42 using System.Web.Caching;
43 using System.Web.Configuration;
44 using System.Web.Management;
45 using System.Web.UI;
46 using System.Web.Util;
47 using Mono.Web.Util;
48 using System.Threading;
49 using System.CodeDom.Compiler;
50 using System.Web.Compilation;
51
52 namespace System.Web
53 {       
54         // CAS - no InheritanceDemand here as the class is sealed
55         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
56         public sealed class HttpRuntime
57         {
58                 static bool domainUnloading;
59                 static SplitOrderedList <string, string> registeredAssemblies;
60                 static QueueManager queue_manager;
61                 static TraceManager trace_manager;
62                 static Cache cache;
63                 static Cache internalCache;
64                 static WaitCallback do_RealProcessRequest;
65                 static HttpWorkerRequest.EndOfSendNotification end_of_send_cb;
66                 static Exception initialException;
67                 static bool firstRun;
68                 static bool assemblyMappingEnabled;
69                 static object assemblyMappingLock = new object ();
70                 static object appOfflineLock = new object ();
71                 static HttpRuntimeSection runtime_section;
72                 
73                 public HttpRuntime ()
74                 {
75
76                 }
77
78                 static HttpRuntime ()
79                 {
80                         firstRun = true;
81
82                         try {
83                                 WebConfigurationManager.Init ();
84                                 SettingsMappingManager.Init ();
85                                 runtime_section = (HttpRuntimeSection) WebConfigurationManager.GetSection ("system.web/httpRuntime");
86                         } catch (Exception ex) {
87                                 initialException = ex;
88                         }
89
90                         // The classes in whose constructors exceptions may be thrown, should be handled the same way QueueManager
91                         // and TraceManager are below. The constructors themselves MUST NOT throw any exceptions - we MUST be sure
92                         // the objects are created here. The exceptions will be dealt with below, in RealProcessRequest.
93                         queue_manager = new QueueManager ();
94                         if (queue_manager.HasException) {
95                                 if (initialException == null)
96                                         initialException = queue_manager.InitialException;
97                                 else {
98                                         Console.Error.WriteLine ("Exception during QueueManager initialization:");
99                                         Console.Error.WriteLine (queue_manager.InitialException);
100                                 }
101                         }
102
103                         trace_manager = new TraceManager ();
104                         if (trace_manager.HasException) {
105                                 if (initialException == null)
106                                         initialException = trace_manager.InitialException;
107                                 else {
108                                         Console.Error.WriteLine ("Exception during TraceManager initialization:");
109                                         Console.Error.WriteLine (trace_manager.InitialException);
110                                 }
111                         }
112
113                         registeredAssemblies = new SplitOrderedList <string, string> (StringComparer.Ordinal);
114                         cache = new Cache ();
115                         internalCache = new Cache ();
116                         internalCache.DependencyCache = internalCache;
117                         do_RealProcessRequest = new WaitCallback (state => {
118                                 try {
119                                         RealProcessRequest (state);
120                                 } catch {}
121                                 });
122                         end_of_send_cb = new HttpWorkerRequest.EndOfSendNotification (EndOfSend);
123                 }
124
125                 internal static SplitOrderedList <string, string> RegisteredAssemblies {
126                         get { return registeredAssemblies; }
127                 }
128                 
129 #region AppDomain handling
130                 internal static bool DomainUnloading {
131                         get { return domainUnloading; }
132                 }
133
134                 [MonoDocumentationNote ("Currently returns path to the application root")]
135                 public static string AspClientScriptPhysicalPath { get { return AppDomainAppPath; } }
136
137                 [MonoDocumentationNote ("Currently returns path to the application root")]
138                 public static string AspClientScriptVirtualPath { get { return AppDomainAppVirtualPath; } }
139                 
140                 //
141                 // http://radio.weblogs.com/0105476/stories/2002/07/12/executingAspxPagesWithoutAWebServer.html
142                 //
143                 public static string AppDomainAppId {
144                         [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.High)]
145                         get {
146                                 //
147                                 // This value should not change across invocations
148                                 //
149                                 string dirname = (string) AppDomain.CurrentDomain.GetData (".appId");
150                                 if ((dirname != null) && (dirname.Length > 0) && SecurityManager.SecurityEnabled) {
151                                         new FileIOPermission (FileIOPermissionAccess.PathDiscovery, dirname).Demand ();
152                                 }
153                                 return dirname;
154                         }
155                 }
156
157                 // Physical directory for the application
158                 public static string AppDomainAppPath {
159                         get {
160                                 string dirname = (string) AppDomain.CurrentDomain.GetData (".appPath");
161                                 if (SecurityManager.SecurityEnabled) {
162                                         new FileIOPermission (FileIOPermissionAccess.PathDiscovery, dirname).Demand ();
163                                 }
164                                 return dirname;
165                         }
166                 }
167
168                 public static string AppDomainAppVirtualPath {
169                         get {
170                                 return (string) AppDomain.CurrentDomain.GetData (".appVPath");
171                         }
172                 }
173
174                 public static string AppDomainId {
175                         [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.High)]
176                         get {
177                                 return (string) AppDomain.CurrentDomain.GetData (".domainId");
178                         }
179                 }
180
181                 public static string AspInstallDirectory {
182                         get {
183                                 string dirname = (string) AppDomain.CurrentDomain.GetData (".hostingInstallDir");
184                                 if ((dirname != null) && (dirname.Length > 0) && SecurityManager.SecurityEnabled) {
185                                         new FileIOPermission (FileIOPermissionAccess.PathDiscovery, dirname).Demand ();
186                                 }
187                                 return dirname;
188                         }
189                 }
190 #endregion
191
192                 static string _actual_bin_directory;
193                 public static string BinDirectory {
194                         get {
195                                 if (_actual_bin_directory == null) {
196                                         string[] parts = AppDomain.CurrentDomain.SetupInformation.PrivateBinPath.Split (';');
197                                         string mypath = AppDomainAppPath;
198                                         string tmp;
199                                         
200                                         foreach (string p in parts) {
201                                                 tmp = Path.Combine (mypath, p);
202                                                 if (Directory.Exists (tmp)) {
203                                                         _actual_bin_directory = tmp;
204                                                         break;
205                                                 }
206                                         }
207
208                                         if (_actual_bin_directory == null)
209                                                 _actual_bin_directory = Path.Combine (mypath, "bin");
210
211                                         if (_actual_bin_directory [_actual_bin_directory.Length - 1] != Path.DirectorySeparatorChar)
212                                                 _actual_bin_directory += Path.DirectorySeparatorChar;
213                                 }
214                                 
215                                 if (SecurityManager.SecurityEnabled)
216                                         new FileIOPermission (FileIOPermissionAccess.PathDiscovery, _actual_bin_directory).Demand ();
217
218                                 return _actual_bin_directory;
219                         }
220                 }
221
222                 public static Cache Cache {
223                         get {
224                                 return cache;
225                         }
226                 }
227
228                 internal static Cache InternalCache {
229                         get {
230                                 return internalCache;
231                         }
232                 }
233                 
234                 public static string ClrInstallDirectory {
235                         get {
236                                 string dirname = Path.GetDirectoryName (typeof (Object).Assembly.Location);
237                                 if ((dirname != null) && (dirname.Length > 0) && SecurityManager.SecurityEnabled) {
238                                         new FileIOPermission (FileIOPermissionAccess.PathDiscovery, dirname).Demand ();
239                                 }
240                                 return dirname;
241                         }
242                 }
243
244                 public static string CodegenDir {
245                         get {
246                                 string dirname = AppDomain.CurrentDomain.SetupInformation.DynamicBase;
247                                 if (SecurityManager.SecurityEnabled) {
248                                         new FileIOPermission (FileIOPermissionAccess.PathDiscovery, dirname).Demand ();
249                                 }
250                                 return dirname;
251                         }
252                 }
253
254                 public static bool IsOnUNCShare {
255                         [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Low)]
256                         get {
257                                 return RuntimeHelpers.IsUncShare;
258                         }
259                 }
260
261                 public static string MachineConfigurationDirectory {
262                         get {
263                                 string dirname = Path.GetDirectoryName (ICalls.GetMachineConfigPath ());
264                                 if ((dirname != null) && (dirname.Length > 0) && SecurityManager.SecurityEnabled) {
265                                         new FileIOPermission (FileIOPermissionAccess.PathDiscovery, dirname).Demand ();
266                                 }
267                                 return dirname;
268                         }
269                 }
270
271                 internal static HttpRuntimeSection Section { get { return runtime_section; } }
272
273                 public static bool UsingIntegratedPipeline { get { return false; } }
274
275                 public static Version IISVersion {
276                         get {
277                                 // Null means not hosted by IIS
278                                 return null;
279                         }
280                 }
281                 
282                 public static Version TargetFramework {
283                         get {
284                                 return runtime_section.TargetFramework;
285                         }
286                 }
287                 
288                 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
289                 public static void Close ()
290                 {
291                         // Remove all items from cache.
292                 }
293
294                 internal static HttpWorkerRequest QueuePendingRequest (bool started_internally)
295                 {
296                         HttpWorkerRequest next = queue_manager.GetNextRequest (null);
297                         if (next == null)
298                                 return null;
299
300                         if (!started_internally) {
301                                 next.StartedInternally = true;
302                                 ThreadPool.QueueUserWorkItem (do_RealProcessRequest, next);
303                                 return null;
304                         }
305                         return next;
306                 }
307
308                 static readonly string[] app_offline_files = {"app_offline.htm", "App_Offline.htm", "APP_OFFLINE.HTM"};
309                 static string app_offline_file;
310                 
311                 static bool AppIsOffline (HttpContext context)
312                 {
313                         if (!HttpApplicationFactory.ApplicationDisabled || app_offline_file == null)
314                                 return false;
315
316                         HttpResponse response = context.Response;
317                         response.Clear ();
318                         response.ContentType = "text/html";
319                         response.ExpiresAbsolute = DateTime.UtcNow;
320                         response.StatusCode = 503;
321                         response.TransmitFile (app_offline_file, true);
322                         
323                         context.Request.ReleaseResources ();
324                         context.Response.ReleaseResources ();
325                         HttpContext.Current = null;
326                         HttpApplication.requests_total_counter.Increment ();
327                         
328                         return true;
329                 }
330
331                 static void AppOfflineFileRenamed (object sender, RenamedEventArgs args)
332                 {
333                         AppOfflineFileChanged (sender, args);
334                 }
335
336                 static void AppOfflineFileChanged (object sender, FileSystemEventArgs args)
337                 {
338                         lock (appOfflineLock) {
339                                 bool offline;
340                                 
341                                 switch (args.ChangeType) {
342                                         case WatcherChangeTypes.Created:
343                                         case WatcherChangeTypes.Changed:
344                                                 offline = true;
345                                                 break;
346
347                                         case WatcherChangeTypes.Deleted:
348                                                 offline = false;
349                                                 break;
350
351                                         case WatcherChangeTypes.Renamed:
352                                                 RenamedEventArgs rargs = args as RenamedEventArgs;
353
354                                                 if (rargs != null &&
355                                                     String.Compare (rargs.Name, "app_offline.htm", StringComparison.OrdinalIgnoreCase) == 0)
356                                                         offline = true;
357                                                 else
358                                                         offline = false;
359                                                 break;
360
361                                         default:
362                                                 offline = false;
363                                                 break;
364                                 }
365                                 SetOfflineMode (offline, args.FullPath);
366                         }
367                 }
368
369                 static void SetOfflineMode (bool offline, string filePath)
370                 {
371                         if (!offline) {
372                                 app_offline_file = null;
373                                 if (HttpApplicationFactory.ApplicationDisabled)
374                                         HttpRuntime.UnloadAppDomain ();
375                         } else {
376                                 app_offline_file = filePath;
377                                 HttpApplicationFactory.DisableWatchers ();
378                                 HttpApplicationFactory.ApplicationDisabled = true;
379                                 InternalCache.InvokePrivateCallbacks ();
380                                 HttpApplicationFactory.Dispose ();
381                         }
382                 }
383                 
384                 static void SetupOfflineWatch ()
385                 {
386                         lock (appOfflineLock) {
387                                 FileSystemEventHandler seh = new FileSystemEventHandler (AppOfflineFileChanged);
388                                 RenamedEventHandler reh = new RenamedEventHandler (AppOfflineFileRenamed);
389
390                                 string app_dir = AppDomainAppPath;
391                                 FileSystemWatcher watcher;
392                                 string offlineFile = null, tmp;
393                                 
394                                 foreach (string f in app_offline_files) {
395                                         watcher = new FileSystemWatcher ();
396                                         watcher.Path = Path.GetDirectoryName (app_dir);
397                                         watcher.Filter = Path.GetFileName (f);
398                                         watcher.NotifyFilter |= NotifyFilters.Size;
399                                         watcher.Deleted += seh;
400                                         watcher.Changed += seh;
401                                         watcher.Created += seh;
402                                         watcher.Renamed += reh;
403                                         watcher.EnableRaisingEvents = true;
404
405                                         tmp = Path.Combine (app_dir, f);
406                                         if (File.Exists (tmp))
407                                                 offlineFile = tmp;
408                                 }
409
410                                 if (offlineFile != null)
411                                         SetOfflineMode (true, offlineFile);
412                         }
413                 }
414                 
415                 static void RealProcessRequest (object o)
416                 {
417                         if (domainUnloading) {
418                                 Console.Error.WriteLine ("Domain is unloading, not processing the request.");
419                                 return;
420                         }
421
422                         HttpWorkerRequest req = (HttpWorkerRequest) o;
423                         bool started_internally = req.StartedInternally;
424                         do {
425                                 Process (req);
426                                 req = QueuePendingRequest (started_internally);
427                         } while (started_internally && req != null);
428                 }
429
430                 static void Process (HttpWorkerRequest req)
431                 {
432                         bool error = false;
433                         if (firstRun) {
434                                 firstRun = false;
435                                 if (initialException != null) {
436                                         FinishWithException (req, HttpException.NewWithCode ("Initial exception", initialException, WebEventCodes.RuntimeErrorRequestAbort));
437                                         error = true;
438                                 }
439                                 SetupOfflineWatch ();
440                         }
441                         HttpContext context = new HttpContext (req);
442                         HttpContext.Current = context;
443                         if (AppIsOffline (context))
444                                 return;
445                         
446                         //
447                         // Get application instance (create or reuse an instance of the correct class)
448                         //
449                         HttpApplication app = null;
450                         if (!error) {
451                                 try {
452                                         app = HttpApplicationFactory.GetApplication (context);
453                                 } catch (Exception e) {
454                                         FinishWithException (req, HttpException.NewWithCode (String.Empty, e, WebEventCodes.RuntimeErrorRequestAbort));
455                                         error = true;
456                                 }
457                         }
458                         
459                         if (error) {
460                                 context.Request.ReleaseResources ();
461                                 context.Response.ReleaseResources ();
462                                 HttpContext.Current = null;
463                         } else {
464                                 context.ApplicationInstance = app;
465                                 req.SetEndOfSendNotification (end_of_send_cb, context);
466
467                                 //
468                                 // Ask application to service the request
469                                 //
470                                 
471                                 IHttpHandler ihh = app;
472 //                              IAsyncResult appiar = ihah.BeginProcessRequest (context, new AsyncCallback (request_processed), context);
473 //                              ihah.EndProcessRequest (appiar);
474                                 ihh.ProcessRequest (context);
475
476                                 HttpApplicationFactory.Recycle (app);
477                         }
478                 }
479
480                 static void EndOfSend (HttpWorkerRequest ignored1, object ignored2)
481                 {
482                 }
483
484                 //
485                 // ProcessRequest method is executed in the AppDomain of the application
486                 //
487                 // Observations:
488                 //    ProcessRequest does not guarantee that `wr' will be processed synchronously,
489                 //    the request can be queued and processed later.
490                 //
491                 [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Medium)]
492                 public static void ProcessRequest (HttpWorkerRequest wr)
493                 {
494                         if (wr == null)
495                                 throw new ArgumentNullException ("wr");
496                         //
497                         // Queue our request, fetch the next available one from the queue
498                         //
499                         HttpWorkerRequest request = queue_manager.GetNextRequest (wr);
500                         if (request == null)
501                                 return;
502
503                         QueuePendingRequest (false);
504                         RealProcessRequest (request);
505                 }
506
507                 
508                 //
509                 // Called when we are shutting down or we need to reload an application
510                 // that has been modified (touch global.asax) 
511                 //
512                 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
513                 public static void UnloadAppDomain ()
514                 {
515                         //
516                         // TODO: call ReleaseResources
517                         //
518                         domainUnloading = true;
519                         HttpApplicationFactory.DisableWatchers ();
520                         ThreadPool.QueueUserWorkItem (delegate {
521                                 try {
522                                         ShutdownAppDomain ();
523                                 } catch (Exception e){
524                                         Console.Error.WriteLine (e);
525                                 }
526                         });
527                 }
528                 //
529                 // Shuts down the AppDomain
530                 //
531                 static void ShutdownAppDomain ()
532                 {
533                         queue_manager.Dispose ();
534                         // This will call Session_End if needed.
535                         InternalCache.InvokePrivateCallbacks ();
536                         // Kill our application.
537                         HttpApplicationFactory.Dispose ();
538                         ThreadPool.QueueUserWorkItem (delegate {
539                                 try {
540                                         DoUnload ();
541                                 } catch {
542                                 }});
543                 }
544
545                 static void DoUnload ()
546                 {
547                         AppDomain.Unload (AppDomain.CurrentDomain);
548                 }
549
550                 static string content503 = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n" +
551                         "<html><head>\n<title>503 Server Unavailable</title>\n</head><body>\n" +
552                         "<h1>Server Unavailable</h1>\n" +
553                         "</body></html>\n";
554
555                 static void FinishWithException (HttpWorkerRequest wr, HttpException e)
556                 {
557                         int code = e.GetHttpCode ();
558                         wr.SendStatus (code, HttpWorkerRequest.GetStatusDescription (code));
559                         wr.SendUnknownResponseHeader ("Connection", "close");
560                         Encoding enc = Encoding.ASCII;
561                         wr.SendUnknownResponseHeader ("Content-Type", "text/html; charset=" + enc.WebName);
562                         string msg = e.GetHtmlErrorMessage ();
563                         byte [] contentBytes = enc.GetBytes (msg);
564                         wr.SendUnknownResponseHeader ("Content-Length", contentBytes.Length.ToString ());
565                         wr.SendResponseFromMemory (contentBytes, contentBytes.Length);
566                         wr.FlushResponse (true);
567                         wr.CloseConnection ();
568                         HttpApplication.requests_total_counter.Increment ();
569                 }
570
571                 //
572                 // This is called from the QueueManager if a request
573                 // can not be processed (load, no resources, or
574                 // appdomain unload).
575                 //
576                 static internal void FinishUnavailable (HttpWorkerRequest wr)
577                 {
578                         wr.SendStatus (503, "Service unavailable");
579                         wr.SendUnknownResponseHeader ("Connection", "close");
580                         Encoding enc = Encoding.ASCII;
581                         wr.SendUnknownResponseHeader ("Content-Type", "text/html; charset=" + enc.WebName);
582                         byte [] contentBytes = enc.GetBytes (content503);
583                         wr.SendUnknownResponseHeader ("Content-Length", contentBytes.Length.ToString ());
584                         wr.SendResponseFromMemory (contentBytes, contentBytes.Length);
585                         wr.FlushResponse (true);
586                         wr.CloseConnection ();
587                         HttpApplication.requests_total_counter.Increment ();
588                 }
589
590                 [AspNetHostingPermissionAttribute(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Unrestricted)]
591                 [MonoDocumentationNote ("Always returns null on Mono")]
592                 public static NamedPermissionSet GetNamedPermissionSet ()
593                 {
594                         return null;
595                 }
596                 
597                 static internal void WritePreservationFile (Assembly asm, string genericNameBase)
598                 {
599                         if (asm == null)
600                                 throw new ArgumentNullException ("asm");
601                         if (String.IsNullOrEmpty (genericNameBase))
602                                 throw new ArgumentNullException ("genericNameBase");
603
604                         string compiled = Path.Combine (AppDomain.CurrentDomain.SetupInformation.DynamicBase,
605                                                         genericNameBase + ".compiled");
606                         PreservationFile pf = new PreservationFile ();
607                         try {
608                                 pf.VirtualPath = String.Concat ("/", genericNameBase, "/");
609
610                                 AssemblyName an = asm.GetName ();
611                                 pf.Assembly = an.Name;
612                                 pf.ResultType = BuildResultTypeCode.TopLevelAssembly;
613                                 pf.Save (compiled);
614                         } catch (Exception ex) {
615                                 throw new HttpException (
616                                         String.Format ("Failed to write preservation file {0}", genericNameBase + ".compiled"),
617                                         ex);
618                         }
619                 }
620                 
621                 static Assembly ResolveAssemblyHandler(object sender, ResolveEventArgs e)
622                 {
623                         AssemblyName an = new AssemblyName (e.Name);
624                         string dynamic_base = AppDomain.CurrentDomain.SetupInformation.DynamicBase;
625                         string compiled = Path.Combine (dynamic_base, an.Name + ".compiled");
626                         string asmPath;
627
628                         if (!File.Exists (compiled)) {
629                                 string fn = an.FullName;
630                                 if (!RegisteredAssemblies.Find ((uint)fn.GetHashCode (), fn, out asmPath))
631                                         return null;
632                         } else {
633                                 PreservationFile pf;
634                                 try {
635                                         pf = new PreservationFile (compiled);
636                                 } catch (Exception ex) {
637                                         throw new HttpException (
638                                                 String.Format ("Failed to read preservation file {0}", an.Name + ".compiled"),
639                                                 ex);
640                                 }
641                                 asmPath = Path.Combine (dynamic_base, pf.Assembly + ".dll");
642                         }
643
644                         if (String.IsNullOrEmpty (asmPath))
645                                 return null;
646                         
647                         Assembly ret = null;
648                         try {
649                                 ret = Assembly.LoadFrom (asmPath);
650                         } catch (Exception) {
651                                 // ignore
652                         }
653                         
654                         return ret;
655                 }
656                 
657                 internal static void EnableAssemblyMapping (bool enable)
658                 {
659                         lock (assemblyMappingLock) {
660                                 if (assemblyMappingEnabled == enable)
661                                         return;
662                                 if (enable)
663                                         AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler (ResolveAssemblyHandler);
664                                 else
665                                         AppDomain.CurrentDomain.AssemblyResolve -= new ResolveEventHandler (ResolveAssemblyHandler);
666                                 assemblyMappingEnabled = enable;
667                         }
668                 }
669                 
670                 internal static TraceManager TraceManager {
671                         get {
672                                 return trace_manager;
673                         }
674                 }
675         }
676 }