//
        // This callback function is called by ETW to enable or disable Tracing dynamically
        //
        public unsafe uint MyCallback(uint requestCode, System.IntPtr context, System.IntPtr bufferSize, byte *byteBuffer)
        {
            try
            {
                BaseEvent *buffer = (BaseEvent *)byteBuffer;
                switch (requestCode)
                {
                case EtwTrace.RequestCodes.EnableEvents:
                    traceHandle = buffer->HistoricalContext;
                    //traceHandle = EtwTrace.GetTraceLoggerHandle((BaseEvent *)buffer);
                    flags     = (uint)EtwTrace.GetTraceEnableFlags((ulong)buffer->HistoricalContext);
                    Level     = (uint)EtwTrace.GetTraceEnableLevel((ulong)buffer->HistoricalContext);
                    IsEnabled = true;
                    break;

                case EtwTrace.RequestCodes.DisableEvents:
                    IsEnabled   = false;
                    traceHandle = 0;
                    Level       = 0;
                    flags       = 0;
                    break;

                default:
                    IsEnabled   = false;
                    traceHandle = 0;
                    break;
                }
                return(0);
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception caught - '{0}'", e.Message);
                return(0);//TODO: Shouldn't we be returning a different value here ?
            }
        }
        public unsafe uint TraceEvent(Guid eventGuid, uint evtype)
        {
            BaseEvent ev;      // Takes up 192 bytes on the stack

            ev.ClientContext = 0;
            ev.Guid          = eventGuid;
            ev.ProviderId    = evtype;
            ev.BufferSize    = 48; // sizeof(EVENT_TRACE_HEADER)

            return(EtwTrace.TraceEvent(traceHandle, (char *)&ev));
        }
        //
        // Registers a Dynamically Generated GUID automatically with an inbuilt callback
        //
        private unsafe uint Register(Guid controlGuid)
        {
            uint status;
            TraceGuidRegistration guidReg = new TraceGuidRegistration();
            Guid dummyGuid = new Guid("{b4955bf0-3af1-4740-b475-99055d3fe9aa}");

            etwProc = new EtwTrace.EtwProc(MyCallback);


            guidReg.Guid      = &dummyGuid;
            guidReg.RegHandle = null;

            status = EtwTrace.RegisterTraceGuids(etwProc, null, ref controlGuid, 1, ref guidReg, null, null, out registrationHandle);

            if (status != 0)
            {
                Console.WriteLine("Register() call Failed with Status {0}", status);
            }
            return(status);
        }
        private unsafe uint EncodeTraceMessage(Guid eventGuid, uint evtype, byte nargs, object formatstring, object data2, object data3, object data4, object data5, object data6, object data7, object data8, object data9)
        {
            uint      status = 0;
            BaseEvent ev;                                                                        // Takes up 208 bytes on the stack
            char *    buffer = stackalloc  char[144 + (1 + 9 * noOfBytesPerArg) / sizeof(char)]; //28 characters would be 56 bytes!!!. We are allocating more space than we require.
            //Header structure:
            //1 byte for number of args
            //3 byte for format string type information,
            //3 bytes each for the type information for a maximum of 8 arguments
            byte * header = (byte *)(buffer + 144);
            uint   offset = 0;
            char * ptr = buffer;
            string s1, s2, s3, s4, s5, s6, s7, s8, s9;
            int    stringMask = 0;
            uint   argCount   = 0;
            byte * ptrHeader  = header;

            s1 = s2 = s3 = s4 = s5 = s6 = s7 = s8 = s9 = defaultString;

            ev.Flags = 0x00120000;             // define Constants
            ev.Guid  = eventGuid;
            //IMP: evtype MUST  be the same as the one specified in the typeve field for CSharp in default.tmf
            ev.ProviderId = evtype;
            MofField *be = null;

            if (header != null)
            {
                be              = &(&ev.UserData)[0];
                header[0]       = (byte)nargs;           //WIN64 Changes (?)
                be->DataPointer = (void *)header;
                be->DataLength  = (uint)(1 + nargs * noOfBytesPerArg);
            }

            if (formatstring == null)
            {
                formatstring = defaultFmtStr;
            }
            if (formatstring != null)
            {
                //data1 would, in most cases, be the format string
                argCount++;
                be  = &(&ev.UserData)[1];
                ptr = buffer + offset;
                if ((s1 = EncodeObject(formatstring, be, ptr, ref offset, ++header)) != null)
                {
                    stringMask |= 0x00000002;
                }
            }

            if (argCount <= nargs)
            {
                argCount++;
                be  = &(&ev.UserData)[2];
                ptr = buffer + offset;
                if ((s2 = EncodeObject(data2, be, ptr, ref offset, header + 1 * noOfBytesPerArg)) != null)
                {
                    stringMask |= 0x00000004;
                }
            }
            if (argCount <= nargs)
            {
                argCount++;
                be  = &(&ev.UserData)[3];
                ptr = buffer + offset;
                if ((s3 = EncodeObject(data3, be, ptr, ref offset, header + 2 * noOfBytesPerArg)) != null)
                {
                    stringMask |= 0x00000008;
                }
            }
            if (argCount <= nargs)
            {
                argCount++;
                be  = &(&ev.UserData)[4];
                ptr = buffer + offset;
                if ((s4 = EncodeObject(data4, be, ptr, ref offset, header + 3 * noOfBytesPerArg)) != null)
                {
                    stringMask |= 0x00000010;
                }
            }
            if (argCount <= nargs)
            {
                argCount++;
                be  = &(&ev.UserData)[5];
                ptr = buffer + offset;
                if ((s5 = EncodeObject(data5, be, ptr, ref offset, header + 4 * noOfBytesPerArg)) != null)
                {
                    stringMask |= 0x00000020;
                }
            }
            if (argCount <= nargs)
            {
                argCount++;
                be  = &(&ev.UserData)[6];
                ptr = buffer + offset;
                if ((s6 = EncodeObject(data6, be, ptr, ref offset, header + 5 * noOfBytesPerArg)) != null)
                {
                    stringMask |= 0x00000040;
                }
            }
            if (argCount <= nargs)
            {
                argCount++;
                be  = &(&ev.UserData)[7];
                ptr = buffer + offset;
                if ((s7 = EncodeObject(data7, be, ptr, ref offset, header + 6 * noOfBytesPerArg)) != null)
                {
                    stringMask |= 0x00000080;
                }
            }
            if (argCount <= nargs)
            {
                argCount++;
                be  = &(&ev.UserData)[8];
                ptr = buffer + offset;
                if ((s8 = EncodeObject(data8, be, ptr, ref offset, header + 7 * noOfBytesPerArg)) != null)
                {
                    stringMask |= 0x00000100;
                }
            }
            if (argCount <= nargs)
            {
                argCount++;
                be  = &(&ev.UserData)[9];
                ptr = buffer + offset;
                if ((s9 = EncodeObject(data9, be, ptr, ref offset, header + 8 * noOfBytesPerArg)) != null)
                {
                    stringMask |= 0x00000200;
                }
            }

            //
            // Now pin all the strings and use the stringMask to pass them over through
            // mofField.
            //

            fixed(char *vptr1 = s1, vptr2 = s2, vptr3 = s3, vptr4 = s4, vptr5 = s5, vptr6 = s6, vptr7 = s7, vptr8 = s8, vptr9 = s9)
            {
                if ((stringMask & 0x00000002) != 0)
                {
                    (&ev.UserData)[1].DataLength = (uint)(s1.Length < 65535 / 2?s1.Length * 2:65535);               //s1.Length*2;

                    (&ev.UserData)[1].DataPointer = (void *)(vptr1);
                }
                if ((stringMask & 0x00000004) != 0)
                {
                    (&ev.UserData)[2].DataLength = (uint)(s2.Length < 65535 / 2?s2.Length * 2:65535);               //s2.Length * 2;

                    (&ev.UserData)[2].DataPointer = (void *)(vptr2);
                }
                if ((stringMask & 0x00000008) != 0)
                {
                    (&ev.UserData)[3].DataLength  = (uint)(s3.Length < 65535 / 2?s3.Length * 2:65535);              //s3.Length * 2;
                    (&ev.UserData)[3].DataPointer = (void *)(vptr3);
                }
                if ((stringMask & 0x00000010) != 0)
                {
                    (&ev.UserData)[4].DataLength  = (uint)(s4.Length < 65535 / 2?s4.Length * 2:65535);              //s4.Length * 2;
                    (&ev.UserData)[4].DataPointer = (void *)(vptr4);
                }
                if ((stringMask & 0x00000020) != 0)
                {
                    (&ev.UserData)[5].DataLength  = (uint)(s5.Length < 65535 / 2?s5.Length * 2:65535);              //s5.Length * 2;
                    (&ev.UserData)[5].DataPointer = (void *)(vptr5);
                }
                if ((stringMask & 0x00000040) != 0)
                {
                    (&ev.UserData)[6].DataLength  = (uint)(s6.Length < 65535 / 2?s6.Length * 2:65535);              //s6.Length * 2;
                    (&ev.UserData)[6].DataPointer = (void *)(vptr6);
                }
                if ((stringMask & 0x00000080) != 0)
                {
                    (&ev.UserData)[7].DataLength  = (uint)(s7.Length < 65535 / 2?s7.Length * 2:65535);              //s7.Length * 2;
                    (&ev.UserData)[7].DataPointer = (void *)(vptr7);
                }
                if ((stringMask & 0x00000100) != 0)
                {
                    (&ev.UserData)[8].DataLength  = (uint)(s8.Length < 65535 / 2?s8.Length * 2:65535);              //s8.Length * 2;
                    (&ev.UserData)[8].DataPointer = (void *)(vptr8);
                }
                if ((stringMask & 0x00000200) != 0)
                {
                    (&ev.UserData)[9].DataLength  = (uint)(s9.Length < 65535 / 2?s9.Length * 2:65535);              //s9.Length * 2;
                    (&ev.UserData)[9].DataPointer = (void *)(vptr9);
                }
                ev.BufferSize = 48 + (argCount + 1) * 16;              //the extra mof field is for the header
                status        = EtwTrace.TraceEvent(traceHandle, (char *)&ev);
            }

            return(status);
        }
        public unsafe uint TraceEvent(Guid eventGuid, uint evtype, object data0, object data1, object data2, object data3, object data4, object data5, object data6, object data7, object data8)
        {
            uint      status = 0;
            BaseEvent ev;                  // Takes up 192 bytes on the stack
            char *    buffer = stackalloc  char[128];
            uint      offset = 0;
            char *    ptr = buffer;
            string    s0, s1, s2, s3, s4, s5, s6, s7, s8;
            int       stringMask = 0;
            uint      argCount   = 0;

            s0 = s1 = s2 = s3 = s4 = s5 = s6 = s7 = s8 = defaultString;

            ev.Flags      = 0x00120000;        // define Constants
            ev.Guid       = eventGuid;
            ev.ProviderId = evtype;
            MofField *be = null;

            if (data0 != null)
            {
                argCount++;
                be = &(&ev.UserData)[0];
                if ((s0 = ProcessOneObject(data0, be, ptr, ref offset)) != null)
                {
                    stringMask |= 0x00000001;
                }
            }
            if (data1 != null)
            {
                argCount++;
                be  = &(&ev.UserData)[1];
                ptr = buffer + offset;
                if ((s1 = ProcessOneObject(data1, be, ptr, ref offset)) != null)
                {
                    stringMask |= 0x00000002;
                }
            }
            if (data2 != null)
            {
                argCount++;
                be  = &(&ev.UserData)[2];
                ptr = buffer + offset;
                if ((s2 = ProcessOneObject(data2, be, ptr, ref offset)) != null)
                {
                    stringMask |= 0x00000004;
                }
            }
            if (data3 != null)
            {
                argCount++;
                be  = &(&ev.UserData)[3];
                ptr = buffer + offset;
                if ((s3 = ProcessOneObject(data3, be, ptr, ref offset)) != null)
                {
                    stringMask |= 0x00000008;
                }
            }
            if (data4 != null)
            {
                argCount++;
                be  = &(&ev.UserData)[4];
                ptr = buffer + offset;
                if ((s4 = ProcessOneObject(data4, be, ptr, ref offset)) != null)
                {
                    stringMask |= 0x00000010;
                }
            }
            if (data5 != null)
            {
                argCount++;
                be  = &(&ev.UserData)[5];
                ptr = buffer + offset;
                if ((s5 = ProcessOneObject(data5, be, ptr, ref offset)) != null)
                {
                    stringMask |= 0x00000020;
                }
            }
            if (data6 != null)
            {
                argCount++;
                be  = &(&ev.UserData)[6];
                ptr = buffer + offset;
                if ((s6 = ProcessOneObject(data6, be, ptr, ref offset)) != null)
                {
                    stringMask |= 0x00000040;
                }
            }
            if (data7 != null)
            {
                argCount++;
                be  = &(&ev.UserData)[7];
                ptr = buffer + offset;
                if ((s7 = ProcessOneObject(data7, be, ptr, ref offset)) != null)
                {
                    stringMask |= 0x00000080;
                }
            }
            if (data8 != null)
            {
                argCount++;
                be  = &(&ev.UserData)[8];
                ptr = buffer + offset;
                if ((s8 = ProcessOneObject(data8, be, ptr, ref offset)) != null)
                {
                    stringMask |= 0x00000100;
                }
            }

            //
            // Now pin all the strings and use the stringMask to pass them over through
            // mofField.
            //

            fixed(char *vptr0 = s0, vptr1 = s1, vptr2 = s2, vptr3 = s3, vptr4 = s4, vptr5 = s5, vptr6 = s6, vptr7 = s7, vptr8 = s8)
            {
                if ((stringMask & 0x00000001) != 0)
                {
                    (&ev.UserData)[0].DataLength  = (uint)s0.Length * 2;
                    (&ev.UserData)[0].DataPointer = (void *)vptr0;
                }
                if ((stringMask & 0x00000002) != 0)
                {
                    (&ev.UserData)[1].DataLength  = (uint)s1.Length * 2;
                    (&ev.UserData)[1].DataPointer = (void *)vptr1;
                }
                if ((stringMask & 0x00000004) != 0)
                {
                    (&ev.UserData)[2].DataLength  = (uint)s2.Length * 2;
                    (&ev.UserData)[2].DataPointer = (void *)vptr2;
                }
                if ((stringMask & 0x00000008) != 0)
                {
                    (&ev.UserData)[3].DataLength  = (uint)s3.Length * 2;
                    (&ev.UserData)[3].DataPointer = (void *)vptr3;
                }
                if ((stringMask & 0x00000010) != 0)
                {
                    (&ev.UserData)[4].DataLength  = (uint)s4.Length * 2;
                    (&ev.UserData)[4].DataPointer = (void *)vptr4;
                }
                if ((stringMask & 0x00000020) != 0)
                {
                    (&ev.UserData)[5].DataLength  = (uint)s5.Length * 2;
                    (&ev.UserData)[5].DataPointer = (void *)vptr5;
                }
                if ((stringMask & 0x00000040) != 0)
                {
                    (&ev.UserData)[6].DataLength  = (uint)s6.Length * 2;
                    (&ev.UserData)[6].DataPointer = (void *)vptr6;
                }
                if ((stringMask & 0x00000080) != 0)
                {
                    (&ev.UserData)[7].DataLength  = (uint)s7.Length * 2;
                    (&ev.UserData)[7].DataPointer = (void *)vptr7;
                }
                if ((stringMask & 0x00000100) != 0)
                {
                    (&ev.UserData)[8].DataLength  = (uint)s8.Length * 2;
                    (&ev.UserData)[8].DataPointer = (void *)vptr8;
                }
                ev.BufferSize = 48 + argCount * 16;
                status        = EtwTrace.TraceEvent(traceHandle, (char *)&ev);
            }

            return(status);
        }