bidPrivateBase.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / ndp / fx / src / Data / System / Data / Common / bidPrivateBase.cs / 2 / bidPrivateBase.cs

                            //------------------------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
// [....]
// Last Modified: 18-Jan-2005 
//----------------------------------------------------------------------------------------------- 
#define UNUSED_CODE     // tag for commenting out unused code
 
//
//  Define the symbol below to enable automatic generation of strongly typed
//  overloads for 'Bid.Trace' and 'Bid.ScopeEnter'.
// 
//#define BID_AUTOSIG
 
//#define CS_V1 
//#define BID_USE_SCOPEAUTO
//#define BID_USE_EXTENSIONS 

//namespace ToBe.Decided {

using System; 
using System.IO;
using System.Text; 
using System.Security; 
using System.Reflection;
using System.Collections; 
using System.Globalization;
using System.Security.Permissions;
using System.Collections.Specialized;
using System.Runtime.InteropServices; 
#if !CS_V1
using System.Runtime.ConstrainedExecution; 
#endif 

#if BID_AUTOSIG 
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
#endif
 
//
//  The C# interface for the BID (Built-In Diagnostics) infrastructure consistis of two files that 
//  implement the wrapper class Bid: 
//
//      internal sealed partial class Bid 
//
//  The main part is implemented in BidPrivateBase.cs and is supposed to be considered
//  as invariant part of the interface.
// 
//  The second part is implemented in assembly (module) specific file, created from
//  AssemblyTemplate_BID.cs and usually renamed to _BID.cs. It is supposed to contain 
//  overloaded methods Trace and ScopeEnter with exact signatures used in the given assembly. 
//
//  SignatureGenerator (available in development cycle when BID_AUTOSIG symbol is defined) 
//  can be used to help generate assembly specific, strongly typed overloads.
//
//  In V1/V1.1 compatibility mode, an artificial inheritace is used in order to to support
//  this model. Every module (or single-module assembly) must use a private copy of 
//
//      internal sealed class Bid : BidPrivateBase 
// 
//  implemented in assembly (module) specific file _BID.cs
// 
//  NOTE:
//      The current technique with two "include" files most likely will be changed,
//      so don't make strong assumptions regarding implementation details.
// 
//      However, the intention is to keep used APIs unchanged, so the upcoming update(s) of the
//      BID infrastructure should not enforce any changes in already instrumented product code. 
// 

#if !CS_V1 

[ComVisible(false)]
internal static partial class Bid
{ 

#else 
 
[ComVisible(false)]
internal class BidPrivateBase 
{
    //
    //  Loader Stub DLL. Can be the assembly itself (Visual Studo 2005 mixed mode dll).
    // 
    protected const string dllName = "BidLdr.dll";
 
#endif 

    //+////////////////////////////////////////////////////////////////////////////////////////// 
    //                                                                                         //
    //                                      INTERFACE                                          //
    //                                                                                         //
    //+////////////////////////////////////////////////////////////////////////////////////////// 
    //
    //  ApiGroup control flags are accessible from attached diagnostic subsystem via corresponding 
    //  delegate, so the output can be enabled/disabled on the fly. 
    //
    internal enum ApiGroup : uint 
    {
        Off         = 0x00000000,

        Default     = 0x00000001,   // Bid.TraceEx (Always ON) 
        Trace       = 0x00000002,   // Bid.Trace, Bid.PutStr
        Scope       = 0x00000004,   // Bid.Scope{Enter|Leave|Auto} 
        Perf        = 0x00000008,   // TBD.. 
        Resource    = 0x00000010,   // TBD..
        Memory      = 0x00000020,   // TBD.. 
        StatusOk    = 0x00000040,   // S_OK, STATUS_SUCCESS, etc.
        Advanced    = 0x00000080,   // Bid.TraceEx

        Pooling     = 0x00001000, 
        Dependency  = 0x00002000,
        StateDump   = 0x00004000, 
 
        MaskBid     = 0x00000FFF,
        MaskUser    = 0xFFFFF000, 
        MaskAll     = 0xFFFFFFFF
    }

    // 
    //  These wrappers simplify coding when/if we want direct access
    //  to the ApiGroup Control Bits. 
    // 
    internal static bool DefaultOn {
        get { return (modFlags & ApiGroup.Default) != 0; } 
    }
    internal static bool TraceOn {
        get { return (modFlags & ApiGroup.Trace) != 0; }
    } 
    internal static bool ScopeOn {
        get { return (modFlags & ApiGroup.Scope) != 0; } 
    } 
    internal static bool PerfOn {
        get { return (modFlags & ApiGroup.Perf) != 0; } 
    }
    internal static bool ResourceOn {
        get { return (modFlags & ApiGroup.Resource) != 0; }
    } 
    internal static bool MemoryOn {
        get { return (modFlags & ApiGroup.Memory) != 0; } 
    } 
    internal static bool StatusOkOn {
        get { return (modFlags & ApiGroup.StatusOk) != 0; } 
    }
    internal static bool AdvancedOn {
        get { return (modFlags & ApiGroup.Advanced) != 0; }
    } 

    internal static bool StateDumpOn { 
        get { return (modFlags & ApiGroup.StateDump) != 0; } 
    }
 
    internal static bool IsOn(ApiGroup flag) {
        return (modFlags & flag) != 0;
    }
 
    internal static bool AreOn(ApiGroup flags) {
        return (modFlags & flags) == flags; 
    } 

 
    private static IntPtr __noData;

    internal static IntPtr NoData {
        get { return __noData; } 
    }
 
    internal static IntPtr ID { 
        get { return modID; }
    } 

    internal static bool IsInitialized {
        get { return modID != NoData; }
    } 

     
    //=////////////////////////////////////////////////////////////////////////////////////////// 
    //
    //  ModeFlags to be used with 'Ex' flavor of API functions (argument "uint flags") 
    //
    internal struct ModeFlags
    {
        internal const uint 
            Default     = 0x00,
            SmartNewLine= 0x01, 
            NewLine     = 0x02, 

            Enabled     = 0x04, 
          /*DemandSrc   = 0x08,*/

            Blob        = 0x10,
            BlobCopy    = 0x12, 
            BlobBinMode = 0x14;
    } 
 
    
    //+////////////////////////////////////////////////////////////////////////////////////////// 
    //
    //  PLAIN STRING OUTPUT
    //
    internal static void PutStr (string str) { 
        if ((modFlags & ApiGroup.Trace) != 0  &&  modID != NoData)
            NativeMethods.PutStr(modID, UIntPtr.Zero, (UIntPtr)ModeFlags.Default, str); 
    } 

    internal static void PutStrLine (string str) { 
        if ((modFlags & ApiGroup.Trace) != 0  &&  modID != NoData)
            NativeMethods.PutStr(modID, UIntPtr.Zero, (UIntPtr)ModeFlags.SmartNewLine, str);
    }
 
    internal static void PutNewLine() {
        if ((modFlags & ApiGroup.Trace) != 0  &&  modID != NoData) 
            NativeMethods.PutStr(modID, UIntPtr.Zero, (UIntPtr)ModeFlags.NewLine, string.Empty); 
    }
 
    internal static void PutStrEx (uint flags, string str) {
        if (modID != NoData)
            NativeMethods.PutStr(modID, UIntPtr.Zero, (UIntPtr)flags, str);
    } 

    internal static void PutSmartNewLine() { 
        if ((modFlags & ApiGroup.Trace) != 0  &&  modID != NoData) 
            NativeMethods.PutStr(modID, UIntPtr.Zero, (UIntPtr)ModeFlags.SmartNewLine, string.Empty);
    } 

    //
    //  for( i = 0; i < strArray.Length; i++ ){
    //      Bid.PutStrEx( Bid.NewLineEx((i % 10) == 0), strArray[idx] ); 
    //  }
    //  Bid.PutSmartNewLine(); 
    // 
    internal static uint NewLineEx(bool addNewLine) {
        return addNewLine ? ModeFlags.SmartNewLine : ModeFlags.Default; 
    }

    
    //+////////////////////////////////////////////////////////////////////////////////////////// 
    //
    //  Main Tracing Facility (More overloads to be provided in assembly-specific file) 
    // 
   #if BID_AUTOSIG
    internal static void Trace(string fmtPrintfW, params object[] args) { 
        SignatureGenerator.Trace (fmtPrintfW, args);
    }
    internal static void TraceEx(uint flags, string fmtPrintfW, params object[] args) {
        SignatureGenerator.TraceEx (flags, fmtPrintfW, args); 
    }
   #endif 
 
    internal static void Trace(string strConst) {
        if ((modFlags & ApiGroup.Trace) != 0  &&  modID != NoData) 
            NativeMethods.Trace(modID, UIntPtr.Zero, UIntPtr.Zero, strConst);
    }
    internal static void TraceEx(uint flags, string strConst) {
        if (modID != NoData) 
            NativeMethods.Trace(modID, UIntPtr.Zero, (UIntPtr)flags, strConst);
    } 
 
    internal static void Trace(string fmtPrintfW, string a1) {
        if ((modFlags & ApiGroup.Trace) != 0  &&  modID != NoData) 
            NativeMethods.Trace(modID, UIntPtr.Zero, UIntPtr.Zero, fmtPrintfW, a1);
    }
    internal static void TraceEx(uint flags, string fmtPrintfW, string a1) {
        if (modID != NoData) 
            NativeMethods.Trace(modID, UIntPtr.Zero, (UIntPtr)flags, fmtPrintfW, a1);
    } 
 
    
    //+////////////////////////////////////////////////////////////////////////////////////////// 
    //
    //  Scope Tracking
    //
    internal static void ScopeLeave(ref IntPtr hScp) { 
        if ((modFlags & ApiGroup.Scope) != 0  && modID != NoData) {
            if (hScp != NoData) NativeMethods.ScopeLeave(modID, UIntPtr.Zero, UIntPtr.Zero, ref hScp); 
        } else { 
            hScp = NoData;  // NOTE: This assignment is necessary, even it may look useless
        } 
    }

    //
    //  (More overloads to be provided in assembly-specific file) 
    //
   #if BID_AUTOSIG 
    internal static void ScopeEnter(out IntPtr hScp, string fmtPrintfW, params object[] args) { 
        SignatureGenerator.ScopeEnter (out hScp, fmtPrintfW, args);
    } 
   #endif


    internal static void ScopeEnter(out IntPtr hScp, string strConst) { 
        if ((modFlags & ApiGroup.Scope) != 0  &&  modID != NoData) {
            NativeMethods.ScopeEnter(modID, UIntPtr.Zero, UIntPtr.Zero, out hScp, strConst); 
        } else { 
            hScp = NoData;
        } 
    }

    internal static void ScopeEnter(out IntPtr hScp, string fmtPrintfW, string a1) {
        if ((modFlags & ApiGroup.Scope) != 0  &&  modID != NoData) { 
            NativeMethods.ScopeEnter(modID, UIntPtr.Zero, UIntPtr.Zero, out hScp, fmtPrintfW, a1);
        } else { 
            hScp = NoData; 
        }
    } 

    internal static void ScopeEnter(out IntPtr hScp, string fmtPrintfW, IntPtr a1) {
        if ((modFlags & ApiGroup.Scope) != 0  &&  modID != NoData) {
            NativeMethods.ScopeEnter(modID, UIntPtr.Zero, UIntPtr.Zero, out hScp, fmtPrintfW, a1); 
        } else {
            hScp = NoData; 
        } 
    }
 
    internal static void ScopeEnter(out IntPtr hScp, string fmtPrintfW, int a1) {
        if ((modFlags & ApiGroup.Scope) != 0  &&  modID != NoData) {
            NativeMethods.ScopeEnter(modID, UIntPtr.Zero, UIntPtr.Zero, out hScp, fmtPrintfW, a1);
        } else { 
            hScp = NoData;
        } 
    } 

    internal static void ScopeEnter(out IntPtr hScp, string fmtPrintfW, int a1, int a2) { 
        if ((modFlags & ApiGroup.Scope) != 0  &&  modID != NoData) {
            NativeMethods.ScopeEnter(modID, UIntPtr.Zero, UIntPtr.Zero, out hScp, fmtPrintfW, a1, a2);
        } else {
            hScp = NoData; 
        }
    } 
 
    
   #if BID_USE_SCOPEAUTO 
    //+//////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Automatic Scope Tracking
    //  NOTEs: 
    //  - This is 'struct', so there are NO HEAP operations and associated perf. penalty;
    //  - Though use it for significant methods, so relative overhead will be inconsiderable; 
    //  - Use 'short' syntax of 'using' expression (no local variable needed): 
    //      void Foo() {
    //          using(new Bid.ScopeAuto("")) { 
    //              // method's body...
    //          }
    //      }
    // 
    internal struct ScopeAuto : IDisposable
    { 
        internal ScopeAuto (string strScopeName) { 
            if ((modFlags & ApiGroup.Scope) != 0  &&  modID != NoData) {
                NativeMethods.ScopeEnter(modID, UIntPtr.Zero, UIntPtr.Zero, out _hscp, strScopeName); 
            } else {
                _hscp = NoData;
            }
        } 
        internal ScopeAuto (string fmtPrintfW, string arg) {
            if ((modFlags & ApiGroup.Scope) != 0  &&  modID != NoData) { 
                NativeMethods.ScopeEnter(modID, UIntPtr.Zero, UIntPtr.Zero, out _hscp, fmtPrintfW, arg); 
            } else {
                _hscp = NoData; 
            }
        }
        internal ScopeAuto (string fmtPrintfW, IntPtr arg) {
            if ((modFlags & ApiGroup.Scope) != 0  &&  modID != NoData) { 
                NativeMethods.ScopeEnter(modID, UIntPtr.Zero, UIntPtr.Zero, out _hscp, fmtPrintfW, arg);
            } else { 
                _hscp = NoData; 
            }
        } 
        internal ScopeAuto (string fmtPrintfW, int arg) {
            if ((modFlags & ApiGroup.Scope) != 0  &&  modID != NoData) {
                NativeMethods.ScopeEnter(modID, UIntPtr.Zero, UIntPtr.Zero, out _hscp, fmtPrintfW, arg);
            } else { 
                _hscp = NoData;
            } 
        } 
        internal ScopeAuto (string fmtPrintfW, int a1, int a2) {
            if ((modFlags & ApiGroup.Scope) != 0  &&  modID != NoData) { 
                NativeMethods.ScopeEnter(modID, UIntPtr.Zero, UIntPtr.Zero, out _hscp, fmtPrintfW, a1, a2);
            } else {
                _hscp = NoData;
            } 
        }
 
        public void Dispose() { 
            if ((modFlags & ApiGroup.Scope) != 0  &&  modID != NoData  &&  _hscp != NoData) {
                NativeMethods.ScopeLeave(modID, UIntPtr.Zero, UIntPtr.Zero, ref _hscp); 
            }
            //  NOTE: In contrast with standalone ScopeLeave,
            //  there is no need to assign "NoData" to _hscp.
        } 

        private IntPtr _hscp; 
 
    } // ScopeAuto
 
   #endif

    
    //+////////////////////////////////////////////////////////////////////////////////////////// 
    //
    //  Output Control 
    // 
    internal static bool Enabled(string traceControlString) {
        return ((modFlags & ApiGroup.Trace) == 0  ||  modID == NoData) 
                ? false
                : NativeMethods.Enabled(modID, UIntPtr.Zero, UIntPtr.Zero, traceControlString);
    }
 
    //
    //  Indentation 
    // 
#if !UNUSED_CODE
    internal struct Indent : IDisposable 
    {
        internal Indent(int oneLevel){
            DASSERT(oneLevel == 1); // We need fake argument (struct can't have ctor with no args)
            In(); 
        }
        public void Dispose(){ 
            Out(); 
        }
 
        internal static void In(){
            if ((modFlags & ApiGroup.Trace) != 0  &&  modID != NoData)
                NativeMethods.Indent(modID, indentIn);
        } 
        internal static void Out(){
            if ((modFlags & ApiGroup.Trace) != 0  &&  modID != NoData) 
                NativeMethods.Indent(modID, indentOut); 
        }
 
    }

    private const int   indentIn  = -1,
                        indentOut = -3; 
#endif
 
     
    //=//////////////////////////////////////////////////////////////////////////////////////////
    // 
    //  Binary output
    //
    internal static void TraceBin(string constStrHeader, byte[] buff, UInt16 length) {
        if (modID != NoData) { 
            if (constStrHeader != null && constStrHeader.Length > 0) {
                NativeMethods.PutStr(modID, UIntPtr.Zero, (UIntPtr)ModeFlags.SmartNewLine, constStrHeader); 
            } 
            if( (UInt16)buff.Length < length ){
                length = (UInt16)buff.Length; 
            }
            NativeMethods.TraceBin( modID, UIntPtr.Zero, (UIntPtr)Bid.ModeFlags.Blob,
                                    " %p %u\n", buff, length );
        } 
    }
 
    internal static void TraceBinEx(byte[] buff, UInt16 length) { 
        if (modID != NoData) {
            if( (UInt16)buff.Length < length ){ 
                length = (UInt16)buff.Length;
            }
            NativeMethods.TraceBin( modID, UIntPtr.Zero, (UIntPtr)Bid.ModeFlags.Blob,
                                    " %p %u\n", buff, length ); 
        }
    } 
 
    
   #if BID_USE_EXTENSIONS 
    //+//////////////////////////////////////////////////////////////////////////////////////////
    //
    //  STRUCTURED EXTENSION
    // 
    internal delegate void ExtDelegate(IntPtr modID, IntPtr objRef, int attr, IntPtr data);
 
    internal static ExtDelegate AddExtension(string extName, ExtDelegate extProc) { 
        AddExtension(extName, extProc, IntPtr.Zero);
        return extProc; 
    }

    internal static ExtDelegate AddExtension(string extName, ExtDelegate extProc, IntPtr extData) {
        if( modID != NoData ){ 
            NativeMethods.AddExtension( modID, DefaultCmdSpace, CtlCmd.AddExtension,
                                        extData, extName, extProc ); 
        } 
        return extProc;
    } 

    internal struct Details
    {
        internal const int 
            Min         = 1,
            Std         = 2, 
            Max         = 7, 
            LevelMask   = 0x07,
            ModeDisco   = 0x08, 
            ModeBinary  = 0x10;
    }

    internal static int LevelOfDetailsEx(int attr) { 
        return (attr & Details.LevelMask);
    } 
    internal static bool InBinaryModeEx(int attr) { 
        return ((attr & Details.ModeBinary) != 0);
    } 
    internal static bool InDiscoveryModeEx(int attr) {
        return ((attr & Details.ModeDisco) != 0);
    }
 
    //
    //  WriteEx to be used in BidExtensions 
    //  (More overloads to be provided in assembly-specific file) 
    //
   #if BID_AUTOSIG 
    internal static void WriteEx(IntPtr hCtx, uint flags, string fmtPrintfW, params object[] args) {
        SignatureGenerator.WriteEx (hCtx, flags, fmtPrintfW, args);
    }
   #endif 

    internal static void WriteEx(IntPtr hCtx, uint flags, string strConst) { 
        NativeMethods.Trace(hCtx, UIntPtr.Zero, (UIntPtr)flags, strConst); 
    }
 
    internal static void WriteEx(IntPtr hCtx, uint flags, string fmtPrintfW, string a1) {
        NativeMethods.Trace(hCtx, UIntPtr.Zero, (UIntPtr)flags, fmtPrintfW, a1);
    }
 
    internal static void WriteBinEx(IntPtr hCtx, byte[] buff, UInt16 length) {
        if (hCtx != NoData) { 
            if( (UInt16)buff.Length < length ) { 
                length = (UInt16)buff.Length;
            } 
            NativeMethods.TraceBin( hCtx, UIntPtr.Zero, (UIntPtr)Bid.ModeFlags.Blob,
                                    " %p %u\n", buff, length );
        }
    } 

 
    // 
    //  Indentation to be used in BidExtensions
    // 
    internal struct WriteIndentEx
    {
        private WriteIndentEx(int noData){ } // no instances, only static methods
 
        internal static void In(IntPtr hCtx){
            NativeMethods.Indent(hCtx, indentIn); 
        } 
        internal static void Out(IntPtr hCtx){
            NativeMethods.Indent(hCtx, indentOut); 
        }
    }

 
    //
    //  Small helpers wrap all the work with GCHandle that we have to do in order to avoid 
    //  object marshalling in P/Invoke. 
    //
    //  NOTE:   Make sure that MakeRef/DelRef are perfectly balanced in order to not leak 
    //          GCHandles. DelRef must be called in 'Dispose|Finalize' or 'finally' block.
    //
    internal static IntPtr MakeRef(object obj) {
        return (IntPtr)GCHandle.Alloc(obj, GCHandleType.Normal); 
    }
    internal static object GetObj(IntPtr objRef) { 
        return ((GCHandle)objRef).Target; 
    }
    internal static void DelRef(IntPtr objRef) { 
        ((GCHandle)objRef).Free();
    }

 
   #endif // BID_USE_EXTENSIONS
     
    //+////////////////////////////////////////////////////////////////////////////////////////// 
    //
    //  SERVICES 
    //

    //
    //  MODULE-WIDE APIGROUP BITS 
    //
    internal static ApiGroup GetApiGroupBits (ApiGroup mask) { 
        return modFlags & mask; 
    }
 
    internal static ApiGroup SetApiGroupBits (ApiGroup mask, ApiGroup bits) {
        lock (_setBitsLock) {
            ApiGroup tmp = modFlags;
            if( mask != ApiGroup.Off ){ 
                modFlags ^= (bits ^ tmp) & mask;
            } 
            return tmp; 
        }
    } 
    private static object _setBitsLock = new object();


    // 
    //  FAST COMMUNICATION WITH THE SUBSYSTEM
    // 
   #if !CS_V1 
    private
   #else 
    protected
   #endif
    struct TouchCode
    { 
        internal const uint
            Reverse         = 1, 
            Unicode         = 2, 

            Extension       = 0 * 4, 

            ObtainItemID    = 1 * 4 + Unicode,
            RecycleItemID   = 1 * 4 + Reverse + Unicode,
            UpdateItemID    = 2 * 4 + Unicode 
        ;
    } 
 
    //
    //  INSTANCE TRACKING IDs 
    //
#if !UNUSED_CODE
    internal static void ObtainItemID(out int itemID, string textID, IntPtr invariant){
        itemID = (modID != NoData) 
            ? NativeMethods.Touch01(modID, textID, TouchCode.ObtainItemID, invariant, IntPtr.Zero)
            : 0; 
    } 
    internal static void ObtainItemID(out int itemID, string textID, uint invariant){
        itemID = (modID != NoData) 
            ? NativeMethods.Touch01(modID, textID, TouchCode.ObtainItemID, (IntPtr)invariant, IntPtr.Zero)
            : 0;
    }
 
    internal static void ObtainItemID(out int itemID, string textID, int invariant){
        itemID = (modID != NoData) 
            ? NativeMethods.Touch01(modID, textID, TouchCode.ObtainItemID, (IntPtr)invariant, IntPtr.Zero) 
            : 0;
    } 
    internal static void RecycleItemID(ref int itemID, string textID){
        if (modID != NoData  &&  itemID != 0) {
            NativeMethods.Touch01(modID, textID, TouchCode.RecycleItemID, (IntPtr)itemID, IntPtr.Zero);
            itemID = 0; 
        }
    } 
 
    internal static void UpdateItemID(ref int itemID, string textID, string associate){
        if (modID != NoData) 
            NativeMethods.Touch02(modID, textID, TouchCode.UpdateItemID, ref itemID, associate);
    }

    internal static void UpdateItemID(ref int itemID, string textID, IntPtr associate){ 
        if (modID != NoData)
            NativeMethods.Touch03(modID, textID, TouchCode.UpdateItemID, ref itemID, associate); 
    } 

    internal static void UpdateItemID(ref int itemID, string textID, int associate){ 
        if (modID != NoData)
            NativeMethods.Touch03(modID, textID, TouchCode.UpdateItemID, ref itemID, (IntPtr)associate);
    }
    internal static void UpdateItemID(ref int itemID, string textID, uint associate){ 
        if (modID != NoData)
            NativeMethods.Touch03(modID, textID, TouchCode.UpdateItemID, ref itemID, (IntPtr)associate); 
    } 
#endif
 
    //
    //  BID-specific Text Metadata
    //
    internal static bool AddMetaText(string metaStr) { 
        if( modID != NoData ){
            NativeMethods.AddMetaText(modID, DefaultCmdSpace, CtlCmd.AddMetaText, IntPtr.Zero, metaStr, IntPtr.Zero); 
        } 
        return true;
    } 

    //
    //  Explicit shutdown of the diagnostic backend.
    //  Note that it's up to BID implementation how to handle this command; it can be just ignored. 
    //
#if !UNUSED_CODE 
    internal static void Shutdown(int arg) { 
        if( modID != NoData ){
            NativeMethods.DllBidCtlProc( modID, DefaultCmdSpace, CtlCmd.Shutdown, 
                                        (IntPtr)arg, IntPtr.Zero, IntPtr.Zero );
        }
    }
#endif 

    //+////////////////////////////////////////////////////////////////////////////////////////// 
    // 
    //  DEBUG-ONLY SERVICES
    // 
    [System.Diagnostics.Conditional("DEBUG")]
    internal static void DTRACE(string strConst) {
        if ((modFlags & ApiGroup.Trace) != 0  &&  modID != NoData) {
            NativeMethods.PutStr(modID, UIntPtr.Zero, (UIntPtr)ModeFlags.SmartNewLine, strConst); 
        }
    } 
 
    [System.Diagnostics.Conditional("DEBUG")]
    internal static void DTRACE(string clrFormatString, params object[] args) { 
        if ((modFlags & ApiGroup.Trace) != 0  &&  modID != NoData) {
            NativeMethods.PutStr(modID, UIntPtr.Zero, (UIntPtr)ModeFlags.SmartNewLine,
                                String.Format(CultureInfo.CurrentCulture, clrFormatString, args));
        } 
    }
 
    [System.Diagnostics.Conditional("DEBUG")] 
    internal static void DASSERT(bool condition) {
        if (!condition) { 
           #if false
            if (0 == nativeAssert(sourceFileLineNumber)) {
                if (!Debugger.IsAttached) {
                    Debugger.Launch(); 
                }
                Debugger.Break(); 
            } 
           #else
            System.Diagnostics.Trace.Assert(false); 
           #endif
        }
    }
 
    
    //+////////////////////////////////////////////////////////////////////////////////////////// 
    //                                                                                         // 
    //                               IMPLEMENTATION DETAILS                                    //
    //                                                                                         // 
    //+//////////////////////////////////////////////////////////////////////////////////////////

    //
    //  modID and modFlags must be unique for each loadable entity (.exe, .dll, .netmodule) 
    //
   #if !CS_V1 
    private 
   #else
    protected 
   #endif
    static  IntPtr modID = internalInitialize();

   #if !CS_V1 
    private
   #else 
    protected 
   #endif
    static  ApiGroup modFlags; 

    private static   string     modIdentity;

    private delegate ApiGroup   CtrlCB( ApiGroup mask, ApiGroup bits ); 
    private static   CtrlCB     ctrlCallback;
 
    // 
    //  Binding Cookie
    // 
    [StructLayout(LayoutKind.Sequential)]
    private class BindingCookie
    {
        internal IntPtr _data; 
        internal BindingCookie()    { _data = (IntPtr)(-1); }
 
       #if !CS_V1 
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
       #endif 
        internal void Invalidate()  { _data = (IntPtr)(-1); }
    };

    private static BindingCookie cookieObject; 
    private static GCHandle      hCookie;
 
    private static void deterministicStaticInit() 
    {
        __noData          = (IntPtr)(-1); 
        __defaultCmdSpace = (IntPtr)(-1);

        modFlags     = ApiGroup.Off;
        modIdentity  = string.Empty; 
        ctrlCallback = new CtrlCB(SetApiGroupBits);
 
        cookieObject = new BindingCookie(); 
        hCookie      = GCHandle.Alloc(cookieObject, GCHandleType.Pinned);
    } 

    //
    //  CONTROL CENTRE
    // 

    private static IntPtr __defaultCmdSpace; 
 
    internal static IntPtr DefaultCmdSpace {
        get { return __defaultCmdSpace; } 
    }

   #if !CS_V1
    private 
   #else
    protected 
   #endif 
    enum CtlCmd : uint
    { 
        //
        //  Standard modifiers for command codes.
        //
        Reverse = 1, 
        Unicode = 2,
 
        // 
        //  Predefined commands are in range [CtlCmd.DcsBase .. CtlCmd.DcsMax]
        //  'Dcs' stands for 'Default Command Space' 
        //
        DcsBase = 268435456 * 4,    // 0x10000000 * 4
        DcsMax  = 402653183 * 4,    // 0x17FFFFFF * 4
 
        //
        //  Control Panel commands are in range [CtlCmd.CplBase .. CtlCmd.CplMax] 
        // 
        CplBase = 402653184 * 4,    // 0x18000000 * 4
        CplMax =  536870911 * 4,    // 0x1FFFFFFF * 4 

        //
        //  Predefined commands (have wrapper functions)
        // 
        CmdSpaceCount   =  0 * 4 + DcsBase,
        CmdSpaceEnum    =  1 * 4 + DcsBase, 
        CmdSpaceQuery   =  2 * 4 + DcsBase, 

        GetEventID      =  5 * 4 + DcsBase + Unicode, 
        ParseString     =  6 * 4 + DcsBase + Unicode,
        AddExtension    =  7 * 4 + DcsBase + Unicode,
        AddMetaText     =  8 * 4 + DcsBase + Unicode,
        AddResHandle    =  9 * 4 + DcsBase + Unicode, 
        Shutdown        = 10 * 4 + DcsBase + Unicode,
 
        LastItem 

    } // CtlCmd 


    internal static IntPtr GetCmdSpaceID (string textID) {
        return  (modID != NoData) 
                ? NativeMethods.GetCmdSpaceID(modID, DefaultCmdSpace, CtlCmd.CmdSpaceQuery, 0, textID, IntPtr.Zero)
                : IntPtr.Zero; 
    } 

     
    //-//////////////////////////////////////////////////////////////////////////////////////////
    //
    //  EntryPoint
    // 
    private const int BidVer = 9210;
 
    [StructLayout(LayoutKind.Sequential)] 
    private struct BIDEXTINFO
    { 
        IntPtr  hModule;
        [MarshalAs(UnmanagedType.LPWStr)]
        string  DomainName;
        int     Reserved2; 
        int     Reserved;
        [MarshalAs(UnmanagedType.LPWStr)] 
        string  ModulePath; 
        IntPtr  ModulePathA;
        IntPtr  pBindCookie; 

        internal BIDEXTINFO(IntPtr hMod, string modPath, string friendlyName, IntPtr cookiePtr)
        {
            hModule     = hMod; 
            DomainName  = friendlyName;
            Reserved2   = 0; 
            Reserved    = 0; 
            ModulePath  = modPath;
            ModulePathA = IntPtr.Zero; 
            pBindCookie = cookiePtr;
        }
    }; // BIDEXTINFO
 
    private static string getIdentity(Module mod)
    { 
        string idStr; 
        object[] attrColl = mod.GetCustomAttributes(typeof(BidIdentityAttribute), true);
        if( attrColl.Length == 0 ){ 
            idStr = mod.Name;
        } else {
            idStr = ((BidIdentityAttribute)attrColl[0]).IdentityString;
        } 
        //Debug.Assert( attrColl.Length == 1 );
        return idStr; 
    } 

    private static string getAppDomainFriendlyName() 
    {
        string name = AppDomain.CurrentDomain.FriendlyName;

        if( name == null || name.Length <= 0 ){ 
            name = "AppDomain.H" + AppDomain.CurrentDomain.GetHashCode();
        } 
        return name; 
    }
 
    private const uint configFlags = 0xD0000000; // ACTIVE_BID|CTLCALLBACK|MASK_PAGE

    [FileIOPermission(SecurityAction.Assert, Unrestricted=true)]
    private static string getModulePath(Module mod) { 
        return mod.FullyQualifiedName;
    } 
 
    private static void initEntryPoint()
    { 
        NativeMethods.DllBidInitialize();

        //
        //  Multi-file assemblies are not supported by current model of the BID managed wrapper. 
        //  The below Marshal.GetHINSTANCE(mod) will return HINSTANCE for the manifest module
        //  instead of actual module, which is Ok because it is the only module 
        //  in the single-file assembly. 
        //
       #if !CS_V1 
        Module mod  = Assembly.GetExecutingAssembly().ManifestModule;
       #else
        Module mod  = Assembly.GetExecutingAssembly().GetModules(false)[0];
       #endif 

        modIdentity = getIdentity(mod); 
        modID = NoData; 

        BIDEXTINFO extInfo = new BIDEXTINFO(Marshal.GetHINSTANCE(mod), 
                                            getModulePath(mod),
                                            getAppDomainFriendlyName(),
                                            hCookie.AddrOfPinnedObject());
 
        NativeMethods.DllBidEntryPoint( ref modID, BidVer, modIdentity,
                                        configFlags, ref modFlags, ctrlCallback, 
                                        ref extInfo, IntPtr.Zero, IntPtr.Zero ); 

        if( modID != NoData ) 
        {
            object[] attrColl = mod.GetCustomAttributes(typeof(BidMetaTextAttribute), true);
            foreach (object obj in attrColl) {
                AddMetaText( ((BidMetaTextAttribute)obj).MetaText ); 
            }
        } 
 
    } // initEntryPoint
 
   #if !CS_V1
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
   #endif
    private static void doneEntryPoint() 
    {
        if (modID == NoData) { 
            modFlags = ApiGroup.Off; 
            return;
        } 

        try {
            NativeMethods.DllBidEntryPoint( ref modID, 0, IntPtr.Zero,
                                            configFlags, ref modFlags, 
                                            IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero );
            NativeMethods.DllBidFinalize(); 
        } 
        catch {
            // 
            //  We do intentionally catch everything because no matter what happens
            //  we don't want any exception to escape when we're in context of a finalizer.
            //  Note that critical exceptions such as ThreadAbortException could be
            //  propagated anyway (CLR 2.0 and above). 
            //
            modFlags = ApiGroup.Off;    // This is 'NoOp', just to not have empty catch block. 
        } 
        finally {
            cookieObject.Invalidate(); 
            modID = NoData;
            modFlags = ApiGroup.Off;
        }
 
    } // doneEntryPoint
 
    // 
    //  Automatic Initialization/Finalization.
    // 
   #if !CS_V1

    private sealed class AutoInit : SafeHandle
    { 
        internal AutoInit() : base(IntPtr.Zero, true) {
            initEntryPoint(); 
            _bInitialized = true; 
        }
        override protected bool ReleaseHandle() { 
            _bInitialized = false;
            doneEntryPoint();
            return true;
        } 
        public override bool IsInvalid {
            get { return !_bInitialized; } 
        } 
        private bool _bInitialized;
    } 

   #else

    [ComVisible(false)] 
    private sealed class AutoInit
    { 
        internal AutoInit() { 
            initEntryPoint();
        } 
        ~AutoInit() {
            doneEntryPoint();
        }
    } 

 
   #endif 

    private static AutoInit ai; 

    private static IntPtr internalInitialize()
    {
        deterministicStaticInit(); 
        ai = new AutoInit();
        return modID; 
    } 

     
    //=//////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Interop calls to pluggable hooks
    // 
   #if !CS_V1
 
    [SuppressUnmanagedCodeSecurity, ComVisible(false)] 
    private static partial class NativeMethods
    { 

   #else

    [SuppressUnmanagedCodeSecurity, ComVisible(false)] 
    private sealed class NativeMethods
    { 
 
   #endif
 
        //
        //  Plain text
        //
        [DllImport(dllName, CharSet=CharSet.Unicode, CallingConvention=CallingConvention.StdCall, 
        EntryPoint="DllBidPutStrW")] extern
        internal static void PutStr(IntPtr hID, UIntPtr src, UIntPtr info, string str); 
 
        //
        //  Trace 
        //
        [DllImport(dllName, CharSet=CharSet.Unicode, CallingConvention=CallingConvention.Cdecl,
        EntryPoint="DllBidTraceCW")] extern
        internal static void Trace(IntPtr hID, UIntPtr src, UIntPtr info, string strConst); 

        [DllImport(dllName, CharSet=CharSet.Unicode, CallingConvention=CallingConvention.Cdecl, 
        EntryPoint="DllBidTraceCW")] extern 
        internal static void Trace(IntPtr hID, UIntPtr src, UIntPtr info, string fmtPrintfW, string a1);
 
        //
        //  Scope
        //
        [DllImport(dllName, EntryPoint="DllBidScopeLeave")] extern 
        internal static void ScopeLeave(IntPtr hID, UIntPtr src, UIntPtr info, ref IntPtr hScp);
 
        [DllImport(dllName, CharSet=CharSet.Unicode, CallingConvention=CallingConvention.Cdecl, 
        EntryPoint="DllBidScopeEnterCW")] extern
        internal static void ScopeEnter(IntPtr hID, UIntPtr src, UIntPtr info, out IntPtr hScp, string strConst); 

        [DllImport(dllName, CharSet=CharSet.Unicode, CallingConvention=CallingConvention.Cdecl,
        EntryPoint="DllBidScopeEnterCW")] extern
        internal static void ScopeEnter(IntPtr hID, UIntPtr src, UIntPtr info, out IntPtr hScp, string fmtPrintfW, string a1); 

        [DllImport(dllName, CharSet=CharSet.Unicode, CallingConvention=CallingConvention.Cdecl, 
        EntryPoint="DllBidScopeEnterCW")] extern 
        internal static void ScopeEnter( IntPtr hID, UIntPtr src, UIntPtr info, out IntPtr hScp,
                                         string fmtPrintfW, int a1); 

        [DllImport(dllName, CharSet=CharSet.Unicode, CallingConvention=CallingConvention.Cdecl,
        EntryPoint="DllBidScopeEnterCW")] extern
        internal static void ScopeEnter( IntPtr hID, UIntPtr src, UIntPtr info, out IntPtr hScp, 
                                         string fmtPrintfW, IntPtr a1);
 
        [DllImport(dllName, CharSet=CharSet.Unicode, CallingConvention=CallingConvention.Cdecl, 
        EntryPoint="DllBidScopeEnterCW")] extern
        internal static void ScopeEnter( IntPtr hID, UIntPtr src, UIntPtr info, out IntPtr hScp, 
                                         string fmtPrintfW, int a1, int a2);


        // 
        //  Output control
        // 
        [DllImport(dllName, CharSet=CharSet.Unicode, EntryPoint="DllBidEnabledW")] extern 
        internal static bool Enabled(IntPtr hID, UIntPtr src, UIntPtr info, string tcs);
 
#if !UNUSED_CODE
        [DllImport(dllName, CharSet=CharSet.Unicode, EntryPoint="DllBidIndent")] extern
        internal static int Indent(IntPtr hID, int nIdx);
#endif 

        [DllImport(dllName, CharSet=CharSet.Unicode, CallingConvention=CallingConvention.Cdecl, 
        EntryPoint="DllBidTraceCW")] extern 
        internal static void TraceBin(IntPtr hID, UIntPtr src, UIntPtr info, string fmtPrintfW, byte[] buff, UInt16 len);
 

#if !UNUSED_CODE
        //
        //  Fast Communication API 
        //
        [DllImport(dllName, CharSet=CharSet.Unicode, EntryPoint="DllBidTouch")] extern 
        internal static int Touch01(IntPtr hID, string textID, uint code, IntPtr arg1, IntPtr arg2); 

        [DllImport(dllName, CharSet=CharSet.Unicode, EntryPoint="DllBidTouch")] extern 
        internal static void Touch02(IntPtr hID, string textID, uint code, ref int itemID, string associate);

        [DllImport(dllName, CharSet=CharSet.Unicode, EntryPoint="DllBidTouch")] extern
        internal static void Touch03(IntPtr hID, string textID, uint code, ref int itemID, IntPtr associate); 

 
        // 
        //  Services
        // 
        [DllImport(dllName, CharSet=CharSet.Unicode, EntryPoint="DllBidCtlProc")] extern
        internal static void DllBidCtlProc( IntPtr hID, IntPtr cmdSpace, CtlCmd cmd,
                                            IntPtr arg1, IntPtr arg2, IntPtr arg3 );
#endif 

        [DllImport(dllName, CharSet=CharSet.Unicode, EntryPoint="DllBidCtlProc")] extern 
        internal static void AddMetaText( IntPtr hID, IntPtr cmdSpace, CtlCmd cmd, IntPtr nop1, 
                                          string txtID, IntPtr nop2);
 
       #if BID_USE_EXTENSIONS
        [DllImport(dllName, CharSet=CharSet.Unicode, EntryPoint="DllBidCtlProc")] extern
        internal static void AddExtension( IntPtr hID, IntPtr cmdSpaceID, CtlCmd cmd,
                                           IntPtr data, string txtID, ExtDelegate proc); 
       #endif
 
       #if !CS_V1 
        [DllImport(dllName, CharSet=CharSet.Ansi, BestFitMapping=false, EntryPoint="DllBidCtlProc")] extern
       #else 
        [DllImport(dllName, CharSet=CharSet.Ansi, EntryPoint="DllBidCtlProc")] extern
       #endif
        internal static IntPtr GetCmdSpaceID( IntPtr hID, IntPtr cmdSpace, CtlCmd cmd, uint noOp,
                                              string txtID, IntPtr NoOp2 ); 

        // 
        //  Initialization / finalization 
        //
       #if !CS_V1 
        [DllImport(dllName, CharSet=CharSet.Ansi, BestFitMapping=false)] extern
       #else
        [DllImport(dllName, CharSet=CharSet.Ansi)] extern
       #endif 
        internal static void DllBidEntryPoint(ref IntPtr hID, int bInitAndVer, string sIdentity,
                                            uint propBits, ref ApiGroup pGblFlags, CtrlCB fAddr, 
                                            ref BIDEXTINFO pExtInfo, IntPtr pHooks, IntPtr pHdr); 

       #if !CS_V1 
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
       #endif
        [DllImport(dllName)] extern
        internal static void DllBidEntryPoint(ref IntPtr hID, int bInitAndVer, IntPtr unused1, 
                                            uint propBits, ref ApiGroup pGblFlags, IntPtr unused2,
                                            IntPtr unused3, IntPtr unused4, IntPtr unused5); 
 
        [DllImport(dllName)] extern
        internal static void DllBidInitialize(); 

       #if !CS_V1
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
       #endif 
        [DllImport(dllName)] extern
        internal static void DllBidFinalize(); 
 
    } // NativeMethods
 
} // Bid{PrivateBase}


//+////////////////////////////////////////////////////////////////////////////////////////////// 
//                                                                                             //
//                                         Attributes                                          // 
//                                                                                             // 
//-//////////////////////////////////////////////////////////////////////////////////////////////
// 
//  [module: BidIdentity("ModuleIdentityString")]
//
[AttributeUsage(AttributeTargets.Module, AllowMultiple=false)]
internal sealed class BidIdentityAttribute : Attribute 
{
    internal BidIdentityAttribute( string idStr ){ 
        _identity = idStr; 
    }
    internal string IdentityString { 
        get { return _identity; }
    }
    string  _identity;
} 

// 
//  [module: BidMetaText(" ...")] 
//  [module: BidMetaText(" ...")]
//  ...etc... 
//
[AttributeUsage(AttributeTargets.Module, AllowMultiple=true)]
internal sealed class BidMetaTextAttribute : Attribute
{ 
    internal BidMetaTextAttribute( string str ){
        _metaText = str; 
    } 
    internal string MetaText {
        get { return _metaText; } 
    }
    string  _metaText;
}
 

 
#if BID_AUTOSIG 
//+//////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                             // 
//                                     SignatureGenerator                                      //
//                                                                                             //
//-//////////////////////////////////////////////////////////////////////////////////////////////
// 
//  NOTE:
//      SignatureGenerator is NOT part of product code. It can be only used in development 
//      cycle in order to help generate strongly typed overloads for Bid.Trace and Bid.ScopeEnter 
//
internal sealed class SignatureGenerator 
{
    private sealed class FmtString
    {
        const string surrogateOutputMarker = "*****"; 

        string _str; 
        bool   _newLine; 

        internal FmtString(string fmt) 
        {
            int len = fmt.Length;
            if( len <= 0 ){
                _newLine = false; 
                _str = string.Empty;
            } else { 
                _newLine = (fmt[len-1] == '\n'); 
                _str = surrogateOutputMarker + (_newLine ? fmt.Substring(0, len-1) : fmt);
            } 
        }

        internal bool WantsNewLine {
            get { return _newLine; } 
        }
        internal string Body { 
            get { return _str; } 
        }
 
    } // FmtString


    [Serializable] 
    private sealed class UniqueSignatures
    { 
        const string invalidTypeSuffix = ".Edit_TypeName_Here"; 

        StringCollection    _sigPool; 
        ArrayList           _numArgsPool;
        StringBuilder       _buf;
        int                 _problemCount;
 
        internal UniqueSignatures()
        { 
            _sigPool      = new StringCollection(); 
            _numArgsPool  = new ArrayList();
            _buf          = new StringBuilder(256); 
            _problemCount = 0;
        }

        internal int Consider(params object[] args) 
        {
            string signature = argList2Sig(args); 
            int    idx1 = _sigPool.IndexOf(signature); 
            if( idx1 < 0 ){
                idx1 = _sigPool.Add(signature); 
                _numArgsPool.Add(args.Length);
            }
           #if !CS_V1
            Bid.DASSERT( NumOfArgs(idx1) == args.Length ); 
           #else
            BidPrivateBase.DASSERT( NumOfArgs(idx1) == args.Length ); 
           #endif 
            return idx1;
        } 

        internal int Count {
            get {
                int cnt = _sigPool.Count; 
               #if !CS_V1
                Bid.DASSERT( cnt == _numArgsPool.Count ); 
               #else 
                BidPrivateBase.DASSERT( cnt == _numArgsPool.Count );
               #endif 
                return cnt;
            }
        }
 
        internal string Signature(int idx) {
            return _sigPool [idx]; 
        } 

        internal int NumOfArgs(int idx) { 
            return (int)_numArgsPool [idx];
        }

 
        string argList2Sig(params object[] args)
        { 
            Type    argType; 
            int     idx = 0;
 
            _buf.Length = 0;    // cleanup StringBuilder

            foreach (object arg in args)
            { 
                _buf.Append(", ");
                if( arg != null ) 
                { 
                    argType = arg.GetType();
                    _buf.Append(argType.FullName); 
                    if( !argType.IsPrimitive && argType != typeof(string) )
                    {
                        _buf.Append(invalidTypeSuffix);
                        _problemCount++; 
                    }
                } 
                else 
                {
                    _buf.Append("System" + invalidTypeSuffix); 
                    _problemCount++;
                }
                _buf.Append(" a");
                _buf.Append(++idx); 
            }
            return _buf.ToString(); 
        } 

        internal void writeSignatures(TextWriter stm, string[] pattern) 
        {
            for (int i = 0; i < this.Count; i++) {
                makeSignature(pattern, this.Signature(i), this.NumOfArgs(i), ref _buf);
                stm.WriteLine(_buf); 
            }
            _buf.Length = 0; 
        } 

        private static void makeSignature(string[] pattern, string argList, int numOfArgs, 
                                          ref StringBuilder buf)
        {
            buf.Length = 0;
            foreach (string patternChunk in pattern) 
            {
                switch (patternChunk) 
                { 
                 case "ARGS":
                    buf.Append(argList); 
                    break;
                 case "ARGUSE":
                    buf.Append(argListUse(numOfArgs));
                    break; 
                 case "ARGNUM":
                    buf.Append(numOfArgs.ToString()); 
                    break; 
                 default:
                    buf.Append(patternChunk); 
                    break;
                }
            }
        } 

        internal void PrepareForIntermediateStore() 
        { 
            _buf.Length = 0;
        } 

    } // UniqueSignatures

     
    //=//////////////////////////////////////////////////////////////////////////////////////////
    // 
    //  SignatureGenerator methods ... 
    //
 
    private static string argListUse(int numOfArgs)
    {
        StringBuilder buf = new StringBuilder();
        for (int idx = 1; idx <= numOfArgs; idx++) { 
            buf.Append(",a");
            buf.Append(idx); 
        } 
        return buf.ToString();
    } 

    private static string dumpArgList(params object[] args)
    {
        StringBuilder buf = new StringBuilder(); 
        foreach( object obj in args ){
            buf.Append(" "); 
            if( obj != null ){ 
                buf.Append(obj.ToString());
            } else { 
                buf.Append("(null)");
            }
        }
        return " [" + buf.ToString().Substring(1) + "]"; 
    }
 
 
    static void writeHeader(TextWriter stm, string modName)
    { 
        int idx = modName.LastIndexOfAny(new char[]{'\\', '/'});
        if (idx > 0) {
            modName = modName.Substring(idx+1);
        } 
        string[] pattern = Templates.Headers.File.Split('^');
 
        foreach (string patternChunk in pattern) { 
            switch (patternChunk) {
             case "MODNAME": 
                stm.Write(modName);
                break;
             default:
                stm.Write(patternChunk); 
                break;
            } 
        } 
    }
 
    //=//////////////////////////////////////////////////////////////////////////////////////////

    private static void fakeOutput(uint flags, string fmt, params object[] args)
    { 
        FmtString fmtStr = new FmtString(fmt);
        string buf = fmtStr.Body + dumpArgList(args); 
        if( fmtStr.WantsNewLine || (flags & (Bid.ModeFlags.NewLine|Bid.ModeFlags.SmartNewLine)) != 0 ){ 
            buf += Environment.NewLine;
        } 
       #if !CS_V1
        Bid.PutStr(buf);
       #else
        BidPrivateBase.PutStr(buf); 
       #endif
    } 
 
    internal static void Trace(string fmtPrintfW, params object[] args)
    { 
        fakeOutput(0, fmtPrintfW, args);
        Buckets.Trace.Consider(args);
        Buckets.Native.Trace.Consider(args);
    } 

    internal static void TraceEx(uint flags, string fmtPrintfW, params object[] args) 
    { 
        fakeOutput(flags, fmtPrintfW, args);
        Buckets.TraceEx.Consider(args); 
        Buckets.Native.Trace.Consider(args);
    }

    internal static void ScopeEnter(out IntPtr hScp, string fmt, params object[] args) 
    {
        FmtString fmtStr = new FmtString(fmt); 
        string buf = fmtStr.Body + dumpArgList(args); 
        buf += Environment.NewLine;
       #if !CS_V1 
        Bid.ScopeEnter(out hScp, "%s", buf);
       #else
        BidPrivateBase.ScopeEnter(out hScp, "%s", buf);
       #endif 
        Buckets.ScopeEnter.Consider(args);
        Buckets.Native.ScopeEnter.Consider(args); 
    } 

   #if BID_USE_EXTENSIONS 
    internal static void WriteEx(IntPtr hCtx, uint flags, string fmtPrintfW, params object[] args)
    {
        //
        //  WARNING: 
        //  PutStr inside fakeOutput uses standard modID but should use hCtx in context of WriteEx.
        //  Shouldn't be a problem in case of generating signatures, because the default 
        //  text-streaming BID implementation makes no difference between modID and hCtx. 
        //  In fact, SignatureGenerator doesn't need pluggable implementation at all.
        // 
        fakeOutput(flags, fmtPrintfW, args);
        Buckets.WriteEx.Consider(args);
        Buckets.Native.Trace.Consider(args);
    } 
   #endif
 
 
    //
    //  Automatic Initialization / Finalization 
    //
    private static Buckets  buckets = null;

    static SignatureGenerator() { 
        buckets = new Buckets();
    } 
 
    
    //=////////////////////////////////////////////////////////////////////////////////////////// 

    private sealed class Buckets
    {
        internal static UniqueSignatures    Trace; 
        internal static UniqueSignatures    TraceEx;
        internal static UniqueSignatures    ScopeEnter; 
        internal static UniqueSignatures    WriteEx; 

        internal struct Native { 
           internal static UniqueSignatures Trace;
           internal static UniqueSignatures ScopeEnter;
        }
 
        private Stream          _tempStore;
        private BinaryFormatter _formatter; 
        private string          _moduleName; 

 
        internal Buckets()
        {
            _tempStore = null;
            _moduleName = getModuleName(); 
            initSignatures();
        } 
 
        ~Buckets()
        { 
            writeFiles();
        }

        private void writeFiles() 
        {
            saveSignatures(); 
 
            TextWriter stm = null;
            try { 
                stm = new StreamWriter(SignatureFileName);
                writeSignatureFile(stm, SignatureFileName);
            }
            finally { 
                if( stm != null ){
                    stm.Close(); 
                    stm = null; 
                }
            } 
        }

        private string TempStoreFileName
        { 
            get { return _moduleName + "_tempstore.tmp"; }
        } 
 
        private string SignatureFileName
        { 
            get { return _moduleName + "_BID.cs"; }
        }

        private string getModuleName() 
        {
            string modName;  // AppDomain.CurrentDomain.BaseDirectory; 
 
           #if !CS_V1
            modName  = Assembly.GetExecutingAssembly().ManifestModule.Name; 
           #else
            modName  = Assembly.GetExecutingAssembly().GetModules(false)[0].Name;
           #endif
 
            int len = modName.LastIndexOf('.');
           #if !CS_V1 
            Bid.DASSERT( len > 0 ); 
           #else
            BidPrivateBase.DASSERT( len > 0 ); 
           #endif
            if( len > 0 ){
                modName = modName.Substring(0, len);
            } 
            return modName;
        } 
 
        Stream tryOpenTempStore(bool bWrite)
        { 
            Stream store = null;
            try {
                store = bWrite ? File.OpenWrite( TempStoreFileName )
                               : File.OpenRead( TempStoreFileName ); 
            }
            catch(FileNotFoundException){ 
                store = null; 
            }
            return store; 
        }

        private void initSignatures()
        { 
            _tempStore = tryOpenTempStore(false);
 
            try { 
                Trace               = newUniqueSignatures();
                TraceEx             = newUniqueSignatures(); 
                ScopeEnter          = newUniqueSignatures();
                WriteEx             = newUniqueSignatures();
                Native.Trace        = newUniqueSignatures();
                Native.ScopeEnter   = newUniqueSignatures(); 
            }
            finally { 
                if( _tempStore != null ){ 
                    _tempStore.Close();
                    _tempStore = null; 
                }
            }
        }
 
        private void saveSignatures()
        { 
            _tempStore = tryOpenTempStore(true); 
            if( _tempStore != null ){
                try { 
                    storeIntermediate(Trace);
                    storeIntermediate(TraceEx);
                    storeIntermediate(ScopeEnter);
                    storeIntermediate(WriteEx); 
                    storeIntermediate(Native.Trace);
                    storeIntermediate(Native.ScopeEnter); 
                } 
                finally {
                    _tempStore.Close(); 
                    _tempStore = null;
                }
            }
        } 

        private UniqueSignatures newUniqueSignatures() 
        { 
            if( _tempStore == null || _tempStore.Length == 0 ){
                return new UniqueSignatures(); 
            }
            if( _formatter == null ){
                _formatter = new BinaryFormatter();
            } 
            return (UniqueSignatures)_formatter.Deserialize(_tempStore);
        } 
 
        private void storeIntermediate(UniqueSignatures usig)
        { 
            if( _formatter == null ){
                _formatter = new BinaryFormatter();
            }
            usig.PrepareForIntermediateStore(); 
            _formatter.Serialize(_tempStore, usig);
        } 
 

        private void writeSignatureFile(TextWriter stm, string moduleName) 
        {
            writeHeader(stm, moduleName);

            if( Trace.Count > 0 ) stm.Write(Templates.Headers.Trace); 
            Trace.writeSignatures(stm, Patterns.Trace);
 
            if( TraceEx.Count > 0 ) stm.Write(Templates.Headers.TraceEx); 
            TraceEx.writeSignatures(stm, Patterns.TraceEx);
 
            if( ScopeEnter.Count > 0 ) stm.Write(Templates.Headers.ScopeEnter);
            ScopeEnter.writeSignatures(stm, Patterns.ScopeEnter);

            if( WriteEx.Count > 0 ) stm.Write(Templates.Headers.WriteEx); 
            WriteEx.writeSignatures(stm, Patterns.WriteEx);
 
            stm.Write(Templates.Headers.Native); 

            Native.Trace.writeSignatures(stm, Patterns.Native.Trace); 
            Native.ScopeEnter.writeSignatures(stm, Patterns.Native.ScopeEnter);


            stm.WriteLine(); 
            stm.WriteLine("    } // Native");
            stm.WriteLine(); 
            stm.WriteLine("} // Bid"); 
        }
 
    } // Buckets


     
    //=//////////////////////////////////////////////////////////////////////////////////////////
 
    struct Templates 
    {
        internal struct Headers 
        {
          #if !CS_V1

            internal const string File = 
            "//-----------------------------------------------------------------------------------\r\n" +
            "// \r\n" + 
            "//     Copyright (c) Microsoft Corporation.  All rights reserved.\r\n" + 
            "// \r\n" +
            "//-----------------------------------------------------------------------------------\r\n" + 
            "\r\n" +
            "using System;\r\n" +
            "using System.Text;\r\n" +
            "using System.Security;\r\n" + 
            "using System.Reflection;\r\n" +
            "using System.Security.Permissions;\r\n" + 
            "using System.Runtime.InteropServices;\r\n" + 
            "\r\n" +
            "internal static partial class Bid\r\n" + 
            "{\r\n" +
            "    //\r\n" +
            "    //  Loader Stub DLL. Can be the assembly itself (mixed mode).\r\n" +
            "    //\r\n" + 
            "    private const string dllName = \"BidLdr.dll\";\r\n" +
            "\r\n" + 
            "\r\n"; 

            internal const string Native = 
            "    //\r\n" +
            "    // Interop calls to pluggable hooks [SuppressUnmanagedCodeSecurity] applied\r\n" +
            "    //\r\n" +
            "    private static partial class NativeMethods\r\n" + 
            "    {\r\n" +
            "\r\n"; 
 
          #else
 
            internal const string File =
            "//-----------------------------------------------------------------------------------\r\n" +
            "// \r\n" +
            "//     Copyright (c) Microsoft Corporation.  All rights reserved.\r\n" + 
            "// \r\n" +
            "//-----------------------------------------------------------------------------------\r\n" + 
            "\r\n" + 
            "using System;\r\n" +
            "using System.Text;\r\n" + 
            "using System.Security;\r\n" +
            "using System.Reflection;\r\n" +
            "using System.Security.Permissions;\r\n" +
            "using System.Runtime.InteropServices;\r\n" + 
            "\r\n" +
            "[ComVisible(false)]\r\n" + 
            "internal sealed class Bid : BidPrivateBase\r\n" + 
            "{\r\n" +
            "    private Bid() {}\r\n" + 
            "\r\n" +
            "\r\n";

            internal const string Native = 
            "    //\r\n" +
            "    // Interop calls to pluggable hooks\r\n" + 
            "    //\r\n" + 
            "    [SuppressUnmanagedCodeSecurity, ComVisible(false)]\r\n" +
            "    private sealed class NativeMethods\r\n" + 
            "    {\r\n" +
            "\r\n";

          #endif 

 
            internal const string Trace = 
            "    //\r\n" +
            "    //  Trace overloads\r\n" + 
            "    //\r\n";

            internal const string TraceEx =
            "    //\r\n" + 
            "    //  TraceEx overloads\r\n" +
            "    //\r\n"; 
 
            internal const string ScopeEnter =
            "    //\r\n" + 
            "    //  ScopeEnter overloads\r\n" +
            "    //\r\n";

            internal const string WriteEx = 
            "    //\r\n" +
            "    //  WriteEx overloads\r\n" + 
            "    //\r\n"; 

 
        } // Headers


        internal const string Trace = 
        "    internal static void Trace(string fmtPrintfW^ARGS^) {\r\n" +
        "        if ((modFlags & ApiGroup.Trace) != 0  &&  modID != NoData)\r\n" + 
        "            NativeMethods.Trace (modID, UIntPtr.Zero, UIntPtr.Zero, fmtPrintfW^ARGUSE^);\r\n" + 
        "    }\r\n";
 
        internal const string TraceEx =
        "    internal static void TraceEx(uint flags, string fmtPrintfW^ARGS^) {\r\n" +
        "        if (modID != NoData)\r\n" +
        "            NativeMethods.Trace (modID, UIntPtr.Zero, (UIntPtr)flags, fmtPrintfW^ARGUSE^);\r\n" + 
        "    }\r\n";
 
        internal const string ScopeEnter = 
        "    internal static void ScopeEnter(out IntPtr hScp, string fmtPrintfW^ARGS^) {\r\n" +
        "        if ((modFlags & ApiGroup.Scope) != 0  &&  modID != NoData) {\r\n" + 
        "            NativeMethods.ScopeEnter (modID, UIntPtr.Zero, UIntPtr.Zero, out hScp, fmtPrintfW^ARGUSE^);\r\n" +
        "        } else {\r\n" +
        "            hScp = NoData;\r\n" +
        "        }\r\n" + 
        "    }\r\n";
 
        internal const string WriteEx = 
        "    internal static void WriteEx(IntPtr hCtx, uint flags, string fmtPrintfW^ARGS^) {\r\n" +
        "        NativeMethods.Trace (hCtx, UIntPtr.Zero, (UIntPtr)flags, fmtPrintfW^ARGUSE^);\r\n" + 
        "    }\r\n";


        internal struct Native 
        {
            internal const string Trace = 
            "        [DllImport(dllName, CharSet=CharSet.Unicode, CallingConvention=CallingConvention.Cdecl, EntryPoint=\"DllBidTraceCW\")] extern\r\n" + 
            "        internal static void Trace (IntPtr hID, UIntPtr src, UIntPtr info, string fmtPrintfW^ARGS^);\r\n";
 
            internal const string ScopeEnter =
            "        [DllImport(dllName, CharSet=CharSet.Unicode, CallingConvention=CallingConvention.Cdecl, EntryPoint=\"DllBidScopeEnterCW\")] extern\r\n" +
            "        internal static void ScopeEnter (IntPtr hID, UIntPtr src, UIntPtr info, out IntPtr hScp, string fmtPrintfW^ARGS^);\r\n";
 
        } // Native
 
 
    } // Templates
 

    private sealed class Patterns
    {
        internal static string[]    Trace; 
        internal static string[]    TraceEx;
        internal static string[]    ScopeEnter; 
        internal static string[]    WriteEx; 

        internal struct Native { 
           internal static string[] Trace;
           internal static string[] ScopeEnter;
        }
 
        static Patterns()
        { 
            init(ref Trace,             Templates.Trace); 
            init(ref TraceEx,           Templates.TraceEx);
            init(ref ScopeEnter,        Templates.ScopeEnter); 
            init(ref WriteEx,           Templates.WriteEx);

            init(ref Native.Trace,      Templates.Native.Trace);
            init(ref Native.ScopeEnter, Templates.Native.ScopeEnter); 
        }
 
        private static void init(ref string[] pattern, string templateString) { 
            pattern = templateString.Split('^');
        } 

    } // Patterns

 
} // SignatureGenerator
 
 
#endif  // BID_AUTOSIG
 
// } // namespace

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK