using Microsoft.SharePoint.Administration; using System; using System.Runtime.InteropServices; namespace SPSolutions.SharePoint.Logging { public static class TraceProvider { private static class NativeMethods { internal enum TraceFlags { TRACE_FLAG_START = 1, TRACE_FLAG_END, TRACE_FLAG_MIDDLE, TRACE_FLAG_ID_AS_ASCII } internal struct EVENT_TRACE_HEADER_CLASS { internal byte Type; internal byte Level; internal ushort Version; } internal struct EVENT_TRACE_HEADER { internal ushort Size; internal ushort FieldTypeFlags; internal TraceProvider.NativeMethods.EVENT_TRACE_HEADER_CLASS Class; internal uint ThreadId; internal uint ProcessId; internal long TimeStamp; internal Guid Guid; internal uint ClientContext; internal uint Flags; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] internal struct ULSTraceHeader { internal ushort Size; internal uint dwVersion; internal uint Id; internal Guid correlationID; internal TraceProvider.NativeMethods.TraceFlags dwFlags; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] internal string wzExeName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] internal string wzProduct; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] internal string wzCategory; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 800)] internal string wzMessage; } internal struct ULSTrace { internal TraceProvider.NativeMethods.EVENT_TRACE_HEADER Header; internal TraceProvider.NativeMethods.ULSTraceHeader ULSHeader; } internal enum WMIDPREQUESTCODE { WMI_GET_ALL_DATA, WMI_GET_SINGLE_INSTANCE, WMI_SET_SINGLE_INSTANCE, WMI_SET_SINGLE_ITEM, WMI_ENABLE_EVENTS, WMI_DISABLE_EVENTS, WMI_ENABLE_COLLECTION, WMI_DISABLE_COLLECTION, WMI_REGINFO, WMI_EXECUTE_METHOD } internal unsafe delegate uint EtwProc(TraceProvider.NativeMethods.WMIDPREQUESTCODE requestCode, IntPtr requestContext, uint* bufferSize, IntPtr buffer); internal const int TRACE_VERSION_CURRENT = 1; internal const int ERROR_SUCCESS = 0; internal const int ERROR_INVALID_PARAMETER = 87; internal const int WNODE_FLAG_TRACED_GUID = 131072; [DllImport("advapi32.dll", CharSet = CharSet.Unicode)] internal unsafe static extern uint RegisterTraceGuids([In] TraceProvider.NativeMethods.EtwProc cbFunc, [In] void* context, [In] ref Guid controlGuid, [In] uint guidCount, IntPtr guidReg, [In] string mofImagePath, [In] string mofResourceName, out ulong regHandle); [DllImport("advapi32.dll", CharSet = CharSet.Unicode)] internal static extern uint UnregisterTraceGuids([In] ulong regHandle); [DllImport("advapi32.dll", CharSet = CharSet.Unicode)] internal static extern ulong GetTraceLoggerHandle([In] IntPtr Buffer); [DllImport("advapi32.dll", SetLastError = true)] internal static extern uint TraceEvent([In] ulong traceHandle, [In] ref TraceProvider.NativeMethods.ULSTrace evnt); } public enum TraceSeverity { Unassigned, CriticalEvent, WarningEvent, InformationEvent, Exception, Assert = 7, Unexpected = 10, Monitorable = 15, High = 20, Medium = 50, Verbose = 100 } private static ulong hTraceLog; private static ulong hTraceReg; public static void WriteTrace(uint tag, TraceProvider.TraceSeverity level, Guid correlationGuid, string exeName, string productName, string categoryName, string message) { TraceProvider.NativeMethods.ULSTrace uLSTrace = default(TraceProvider.NativeMethods.ULSTrace); uLSTrace.Header.Size = (ushort)Marshal.SizeOf(typeof(TraceProvider.NativeMethods.ULSTrace)); uLSTrace.Header.Flags = 131072u; uLSTrace.ULSHeader.dwVersion = 1u; uLSTrace.ULSHeader.dwFlags = TraceProvider.NativeMethods.TraceFlags.TRACE_FLAG_ID_AS_ASCII; uLSTrace.ULSHeader.Size = (ushort)Marshal.SizeOf(typeof(TraceProvider.NativeMethods.ULSTraceHeader)); uLSTrace.ULSHeader.Id = tag; uLSTrace.Header.Class.Level = (byte)level; uLSTrace.ULSHeader.wzExeName = exeName; uLSTrace.ULSHeader.wzProduct = productName; uLSTrace.ULSHeader.wzCategory = categoryName; uLSTrace.ULSHeader.wzMessage = message; uLSTrace.ULSHeader.correlationID = correlationGuid; if (message.Length < 800) { ushort num = (ushort)((800 - (message.Length + 1)) * 2); uLSTrace.Header.Size = (ushort)(uLSTrace.Header.Size - num); uLSTrace.ULSHeader.Size = (ushort)(uLSTrace.ULSHeader.Size - num); } if (TraceProvider.hTraceLog != 0uL) { TraceProvider.NativeMethods.TraceEvent(TraceProvider.hTraceLog, ref uLSTrace); } } public static void WriteMultiLineTrace(uint tag, TraceProvider.TraceSeverity level, Guid correlationGuid, string exeName, string productName, string categoryName, string message) { int num = 700; int i = 0; int num2 = 1; if (message.Length <= num) { TraceProvider.WriteTrace(tag, level, correlationGuid, exeName, productName, categoryName, message); return; } TraceProvider.WriteTrace(tag, level, correlationGuid, exeName, productName, categoryName, string.Format("{0}", message.Substring(i, num))); int num3; for (i = num + 1; i < message.Length; i += num3) { if (message.Length - i >= num) { num3 = num; } else { num3 = message.Length - i; } TraceProvider.WriteTrace(tag, level, correlationGuid, exeName, productName, categoryName, string.Format("{0}...{1}", num2, message.Substring(i, num3))); num2++; } } public static void WriteMultiLineTrace(uint tag, TraceProvider.TraceSeverity level, Guid correlationGuid, string exeName, string productName, string categoryName, string lineheader, string message) { int num = 700; int i = 0; int num2 = 1; if (message.Length <= num) { TraceProvider.WriteTrace(tag, level, correlationGuid, exeName, productName, categoryName, message); return; } TraceProvider.WriteTrace(tag, level, correlationGuid, exeName, productName, categoryName, string.Format("{0}0...{1}", lineheader, message.Substring(i, num))); int num3; for (i = num + 1; i < message.Length; i += num3) { if (message.Length - i >= num) { num3 = num; } else { num3 = message.Length - i; } TraceProvider.WriteTrace(tag, level, correlationGuid, exeName, productName, categoryName, string.Format("{0}{1}...{2}", lineheader, num2, message.Substring(i, num3))); num2++; } } public static void RegisterTraceProvider() { SPFarm local = SPFarm.Local; Guid traceSessionGuid = local.TraceSessionGuid; unsafe { TraceProvider.NativeMethods.RegisterTraceGuids(new TraceProvider.NativeMethods.EtwProc(TraceProvider.ControlCallback), null, ref traceSessionGuid, 0u, IntPtr.Zero, null, null, out TraceProvider.hTraceReg); } } public static void UnregisterTraceProvider() { TraceProvider.NativeMethods.UnregisterTraceGuids(TraceProvider.hTraceReg); } public static uint TagFromString(string wzTag) { return (uint)((uint)wzTag[0] << 24 | (uint)wzTag[1] << 16 | (uint)wzTag[2] << 8 | wzTag[3]); } private unsafe static uint ControlCallback(TraceProvider.NativeMethods.WMIDPREQUESTCODE RequestCode, IntPtr Context, uint* InOutBufferSize, IntPtr Buffer) { uint result; switch (RequestCode) { case TraceProvider.NativeMethods.WMIDPREQUESTCODE.WMI_ENABLE_EVENTS: TraceProvider.hTraceLog = TraceProvider.NativeMethods.GetTraceLoggerHandle(Buffer); result = 0u; break; case TraceProvider.NativeMethods.WMIDPREQUESTCODE.WMI_DISABLE_EVENTS: TraceProvider.hTraceLog = 0uL; result = 0u; break; default: result = 87u; break; } *InOutBufferSize = 0u; return result; } } }