EventLogEntry.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / fx / src / Services / Monitoring / system / Diagnosticts / EventLogEntry.cs / 1 / EventLogEntry.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Diagnostics { 
    using System.Text; 
    using System.Runtime.InteropServices;
    using System.Runtime.Serialization; 
    using System.ComponentModel;
    using System.Diagnostics;
    using Microsoft.Win32;
    using Microsoft.Win32.SafeHandles; 
    using System;
    using System.Security; 
    using System.Security.Permissions; 
    using System.IO;
    using System.Globalization; 
    using System.Runtime.Versioning;

    /// 
    ///     
    ///    
    ///    encapsulates a single record in the NT event log. 
    ///  
    /// 
    [ 
    ToolboxItem(false),
    DesignTimeVisible(false),
    Serializable,
    ] 
    public sealed class EventLogEntry : Component, ISerializable {
        internal byte[] dataBuf; 
        internal int bufOffset; 
        private EventLog owner;
        private string category; 
        private string message;

        // make sure only others in this package can create us
        internal EventLogEntry(byte[] buf, int offset, EventLog log) { 
            this.dataBuf = buf;
            this.bufOffset = offset; 
            this.owner = log; 

            GC.SuppressFinalize(this); 
        }

        /// 
        ///  
        /// 
        private EventLogEntry(SerializationInfo info, StreamingContext context) { 
            dataBuf = (byte[])info.GetValue("DataBuffer", typeof(byte[])); 
            string logName = info.GetString("LogName");
            string machineName = info.GetString("MachineName"); 
            owner = new EventLog(logName, machineName, "");
            GC.SuppressFinalize(this);
        }
 
        /// 
        ///     
        ///       Gets the name of the computer on which this entry was generated. 
        ///
        ///     
        /// 
        [MonitoringDescription(SR.LogEntryMachineName)]
        public string MachineName {
            get { 
                // first skip over the source name
                int pos = bufOffset + FieldOffsets.RAWDATA; 
                while (CharFrom(dataBuf, pos) != '\0') 
                    pos += 2;
                pos += 2; 
                char ch = CharFrom(dataBuf, pos);
                StringBuilder buf = new StringBuilder();
                while (ch != '\0') {
                    buf.Append(ch); 
                    pos += 2;
                    ch = CharFrom(dataBuf, pos); 
                } 
                return buf.ToString();
            } 
        }

        /// 
        ///     
        ///       Gets the binary data associated with the entry.
        /// 
        ///     
        /// 
        [ 
        MonitoringDescription(SR.LogEntryData)
        ]
        public byte[] Data {
            get { 
                int dataLen = IntFrom(dataBuf, bufOffset + FieldOffsets.DATALENGTH);
                byte[] data = new byte[dataLen]; 
                Array.Copy(dataBuf, bufOffset + IntFrom(dataBuf, bufOffset + FieldOffsets.DATAOFFSET), 
                           data, 0, dataLen);
                return data; 
            }
        }

        /* 
        /// 
        ///     
        ///       Copies the binary data in the  member into an 
        ///       array.
        ///     
        /// 
        /// 
        ///    
        ///       An array of type . 
        ///    
        ///  
        ///  
        public Byte[] getDataBytes() {
            Byte[] data = new Byte[rec.dataLength]; 
            for (int i = 0; i < data.Length; i++)
                data[i] = new Byte(rec.buf[i]);
            return data;
        } 
        */
 
        ///  
        ///    
        ///       Gets the index of this entry in the event 
        ///       log.
        ///    
        /// 
        [MonitoringDescription(SR.LogEntryIndex)] 
        public int Index {
            get { 
                return IntFrom(dataBuf, bufOffset + FieldOffsets.RECORDNUMBER); 
            }
        } 

        /// 
        ///    
        ///       Gets the text associated with the  for this entry. 
        ///
        ///     
        ///  
        [MonitoringDescription(SR.LogEntryCategory)]
        public string Category { 
            get {
                if (category == null) {
                    string dllName = GetMessageLibraryNames("CategoryMessageFile");
                    string cat = owner.FormatMessageWrapper(dllName, (uint) CategoryNumber, null); 
                    if (cat == null)
                        category = "(" + CategoryNumber.ToString(CultureInfo.CurrentCulture) + ")"; 
                    else 
                        category = cat;
                } 

                return category;
            }
        } 

        ///  
        ///     
        ///       Gets the application-specific category number for this entry
        /// 
        ///    
        /// 
        [
        MonitoringDescription(SR.LogEntryCategoryNumber) 
        ]
        public short CategoryNumber { 
            get { 
                return ShortFrom(dataBuf, bufOffset + FieldOffsets.EVENTCATEGORY);
            } 
        }

        /// 
        ///     
        ///       Gets the application-specific event indentifier of this entry.
        /// 
        ///     
        /// 
        [ 
        MonitoringDescription(SR.LogEntryEventID),
        Obsolete("This property has been deprecated.  Please use System.Diagnostics.EventLogEntry.InstanceId instead.  http://go.microsoft.com/fwlink/?linkid=14202")
        ]
        public int EventID { 
            get {
                // Apparently the top 2 bits of this number are not 
                // always 0. Strip them so the number looks nice to the user. 
                // The problem is, if the user were to want to call FormatMessage(),
                // they'd need these two bits. 
                return IntFrom(dataBuf, bufOffset + FieldOffsets.EVENTID) & 0x3FFFFFFF;
            }
        }
 
        /// 
        ///     
        /// 
        ///       Gets the type
        ///       of this entry. 
        ///
        ///    
        /// 
        [MonitoringDescription(SR.LogEntryEntryType)] 
        public EventLogEntryType EntryType {
            get { 
                return(EventLogEntryType) ShortFrom(dataBuf, bufOffset + FieldOffsets.EVENTTYPE); 
            }
        } 

        /// 
        ///    
        ///       Gets the localized message corresponding to this event entry. 
        ///
        ///     
        ///  
        [
        MonitoringDescription(SR.LogEntryMessage), 
        Editor("System.ComponentModel.Design.BinaryEditor, " + AssemblyRef.SystemDesign, "System.Drawing.Design.UITypeEditor, " + AssemblyRef.SystemDrawing)
        ]
        public string Message {
            get { 
                if (message == null) {
                    string dllNames = GetMessageLibraryNames("EventMessageFile"); 
                    int msgId =   IntFrom(dataBuf, bufOffset + FieldOffsets.EVENTID); 
                    string msg = owner.FormatMessageWrapper(dllNames, (uint)msgId, ReplacementStrings);
                    if (msg == null) { 
                        StringBuilder msgBuf = new StringBuilder(SR.GetString(SR.MessageNotFormatted, msgId, Source));
                        string[] strings = ReplacementStrings;
                        for (int i = 0; i < strings.Length; i++) {
                            if (i != 0) 
                                msgBuf.Append(", ");
                            msgBuf.Append("'"); 
                            msgBuf.Append(strings[i]); 
                            msgBuf.Append("'");
                        } 
                        msg = msgBuf.ToString();
                    }
                    else
                        msg = ReplaceMessageParameters( msg, ReplacementStrings ); 
                    message = msg;
                } 
 
                return message;
            } 
        }

        /// 
        ///     
        ///       Gets the name of the application that generated this event.
        ///     
        ///  
        [MonitoringDescription(SR.LogEntrySource)]
        public string Source { 
            get {
                StringBuilder buf = new StringBuilder();
                int pos = bufOffset + FieldOffsets.RAWDATA;
 
                char ch = CharFrom(dataBuf, pos);
                while (ch != '\0') { 
                    buf.Append(ch); 
                    pos += 2;
                    ch = CharFrom(dataBuf, pos); 
                }

                return buf.ToString();
            } 
        }
 
        ///  
        ///    
        ///       Gets the replacement strings 
        ///       associated with the entry.
        ///
        ///    
        ///  
        [MonitoringDescription(SR.LogEntryReplacementStrings)]
        public string[] ReplacementStrings { 
            get { 
                string[] strings = new string[ShortFrom(dataBuf, bufOffset + FieldOffsets.NUMSTRINGS)];
                int i = 0; 
                int bufpos = bufOffset + IntFrom(dataBuf, bufOffset + FieldOffsets.STRINGOFFSET);
                StringBuilder buf = new StringBuilder();
                while (i < strings.Length) {
                    char ch = CharFrom(dataBuf, bufpos); 
                    if (ch != '\0')
                        buf.Append(ch); 
                    else { 
                        strings[i] = buf.ToString();
                        i++; 
                        buf = new StringBuilder();
                    }
                    bufpos += 2;
                } 
                return strings;
            } 
        } 

        [ 
            MonitoringDescription(SR.LogEntryResourceId),
            ComVisible(false)
        ]
        public Int64 InstanceId { 
            get {
                return (UInt32)IntFrom(dataBuf, bufOffset + FieldOffsets.EVENTID); 
            } 
        }
 
#if false
        internal string StringsBuffer {
            get {
                StringBuilder buf = new StringBuilder(); 
                int bufpos = bufOffset + IntFrom(dataBuf, bufOffset + FieldOffsets.STRINGOFFSET);
                int i = 0; 
                int numStrings = ShortFrom(dataBuf, bufOffset + FieldOffsets.NUMSTRINGS); 
                while (i < numStrings) {
                    char ch = CharFrom(dataBuf, bufpos); 
                    buf.Append(ch);
                    bufpos += 2;
                    if (ch == '\0')
                        i++; 
                }
                return buf.ToString(); 
            } 
        }
#endif 

        /// 
        ///    
        ///       Gets the time at which this event was generated, in local time. 
        ///
        ///     
        ///  
        [MonitoringDescription(SR.LogEntryTimeGenerated)]
        public DateTime TimeGenerated { 
            get {
                return beginningOfTime.AddSeconds(IntFrom(dataBuf, bufOffset + FieldOffsets.TIMEGENERATED)).ToLocalTime();
            }
        } 

        ///  
        ///     
        ///       Gets
        ///       the time at which this event was written to the log, in local time. 
        ///
        ///    
        /// 
        [MonitoringDescription(SR.LogEntryTimeWritten)] 
        public DateTime TimeWritten {
            get { 
                return beginningOfTime.AddSeconds(IntFrom(dataBuf, bufOffset + FieldOffsets.TIMEWRITTEN)).ToLocalTime(); 
            }
        } 

        /// 
        ///    
        ///       Gets the name 
        ///       of the user responsible for this event.
        ///     
        ///  
        [MonitoringDescription(SR.LogEntryUserName)]
        public string UserName { 
            get {
                int sidLen = IntFrom(dataBuf, bufOffset + FieldOffsets.USERSIDLENGTH);
                if (sidLen == 0)
                    return null; 
                byte[] sid = new byte[sidLen];
                Array.Copy(dataBuf, bufOffset + IntFrom(dataBuf, bufOffset + FieldOffsets.USERSIDOFFSET), 
                           sid, 0, sid.Length); 
                int[] nameUse = new int[1];
                char[] name = new char[1024]; 
                char[] refDomName = new char[1024];
                int[] nameLen = new int[] {1024};
                int[] refDomNameLen = new int[] {1024};
                bool success = UnsafeNativeMethods.LookupAccountSid(MachineName, sid, name, nameLen, refDomName, refDomNameLen, nameUse); 
                if (!success) {
                    return ""; 
                    // NOTE, [....]: it would be nice to return error info, but the only right way to do that 
                    // is to throw an exception. People don't want exceptions thrown in the property though.
#if false 
                    if (Marshal.GetLastWin32Error() == ERROR_NONE_MAPPED)
                        // There are some SIDs (evidently rare) that are legitimate SIDs but don't
                        // have a mapping to a name.
                        return ""; 
                    else
                        throw new InvalidOperationException(SR.GetString(SR.NoAccountInfo), SharedUtils.CreateSafeWin32Exception()); 
#endif 
                }
                StringBuilder username = new StringBuilder(); 
                username.Append(refDomName, 0, refDomNameLen[0]);
                username.Append("\\");
                username.Append(name, 0, nameLen[0]);
                return username.ToString(); 
            }
        } 
 
        private char CharFrom(byte[] buf, int offset) {
            return(char) ShortFrom(buf, offset); 
        }

        /// 
        ///     
        ///       Performs a comparison between two event log entries.
        /// 
        ///     
        /// 
        public bool Equals(EventLogEntry otherEntry) { 
            if (otherEntry == null)
                return false;
            int ourLen = IntFrom(dataBuf, bufOffset + FieldOffsets.LENGTH);
            int theirLen = IntFrom(otherEntry.dataBuf, otherEntry.bufOffset + FieldOffsets.LENGTH); 
            if (ourLen != theirLen) {
                return false; 
            } 
            int min = bufOffset;
            int max = bufOffset + ourLen; 
            int j = otherEntry.bufOffset;
            for (int i = min; i < max; i++, j++)
                if (dataBuf[i] != otherEntry.dataBuf[j]) {
                    return false; 
                }
            return true; 
        } 

        private int IntFrom(byte[] buf, int offset) { 
            // assumes Little Endian byte order.
            return(unchecked((int)0xFF000000) & (buf[offset+3] << 24)) | (0xFF0000 & (buf[offset+2] << 16)) |
            (0xFF00 & (buf[offset+1] << 8)) | (0xFF & (buf[offset]));
        } 

        // Replacing parameters '%n' in formated message using 'ParameterMessageFile' registry key. 
        internal string ReplaceMessageParameters( String msg,  string[] insertionStrings )   { 

            int percentIdx = msg.IndexOf('%'); 
            if ( percentIdx < 0 )
                return msg;     // no '%' at all

            int startCopyIdx     = 0;        // start idx of last [....] msg chars to copy 
            int msgLength   = msg.Length;
            StringBuilder buf = new StringBuilder(); 
            string paramDLLNames = GetMessageLibraryNames("ParameterMessageFile"); 

            while ( percentIdx >= 0 ) { 
                string param = null;

                // Convert numeric string after '%' to paramMsgID number.
                int lasNumIdx =  percentIdx + 1; 
                while ( lasNumIdx < msgLength && Char.IsDigit(msg, lasNumIdx) )
                    lasNumIdx++; 
 
                uint paramMsgID = 0;
 
                // If we can't parse it, leave the paramMsgID as zero.  We'll skip the replacement and just put
                // the %xxxx into the final message.
                if (lasNumIdx != percentIdx + 1 )
                    UInt32.TryParse( msg.Substring(percentIdx + 1, lasNumIdx - percentIdx - 1), out paramMsgID); 

                if ( paramMsgID != 0 ) 
                    param = owner.FormatMessageWrapper( paramDLLNames, paramMsgID, insertionStrings); 

                if ( param != null ) { 
                    if ( percentIdx > startCopyIdx )
                        buf.Append(msg, startCopyIdx, percentIdx - startCopyIdx);    // original chars from msg
                    buf.Append(param);
                    startCopyIdx = lasNumIdx; 
                }
 
                percentIdx = msg.IndexOf('%', percentIdx + 1); 
            }
 
            if ( msgLength - startCopyIdx > 0 )
                buf.Append(msg, startCopyIdx, msgLength - startCopyIdx);          // last span of original msg
            return buf.ToString();
        } 

        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)] 
        private static RegistryKey GetSourceRegKey(string logName, string source, string machineName) {
            RegistryKey eventKey = null; 
            RegistryKey logKey   = null;

            try {
                eventKey = EventLog.GetEventLogRegKey(machineName, false); 
                if (eventKey == null)
                    return null; 
                if (logName == null) 
                    logKey = eventKey.OpenSubKey("Application", /*writable*/false);
                else 
                    logKey = eventKey.OpenSubKey(logName, /*writable*/false);
                if (logKey == null)
                    return null;
                return logKey.OpenSubKey(source, /*writable*/false); 
            }
            finally { 
                if (eventKey != null) eventKey.Close(); 
                if (logKey != null) logKey.Close();
            } 

        }

        // ----------------------------------------------------------------------------- 
        // Returns DLL names list.
        // libRegKey can be: "EventMessageFile", "CategoryMessageFile", "ParameterMessageFile" 
        private string GetMessageLibraryNames(string libRegKey ) { 
            // get the value stored in the registry
 
            string fileName = null;
            RegistryKey regKey = null;
            try {
                regKey = GetSourceRegKey(owner.Log, Source, owner.MachineName); 
                if (regKey != null) {
                    if (owner.MachineName == ".") 
                        fileName = (string)regKey.GetValue(libRegKey); 
                    else
                        fileName = (string)regKey.GetValue(libRegKey, null, RegistryValueOptions.DoNotExpandEnvironmentNames); 
                }
            }
            finally {
                if (regKey != null) 
                    regKey.Close();
            } 
 
            if (fileName == null)
                return null; 

            // convert any environment variables to their current values
            // (the key might have something like %systemroot% in it.)
            // if we're looking at a remote machine, just try to replace %systemroot% at the beginning 
            if (owner.MachineName != ".") {
                if (fileName.EndsWith(EventLog.DllName, StringComparison.Ordinal))  { 
                    // if it's our EventLogMessages.dll, just use the local copy 
                    return EventLog.GetDllPath(".");
                } 
                else if (String.Compare(fileName, 0, "%systemroot%", 0, 12, StringComparison.OrdinalIgnoreCase) == 0) {
                    // the final length is:
                    // fileName.Length + owner.MachineName.Length
                    // + 2 for the double slash 
                    // + 7 for the \admin$
                    // - 12 for the %systemroot% we're removing. 
                    StringBuilder result = new StringBuilder(fileName.Length + owner.MachineName.Length - 3); 
                    result.Append(@"\\");
                    result.Append(owner.MachineName); 
                    result.Append(@"\admin$");
                    result.Append(fileName, 12, fileName.Length - 12);
                    return result.ToString();
                } 
                else if (fileName[1] == ':') {
                    StringBuilder result = new StringBuilder(fileName.Length + owner.MachineName.Length + 3); 
                    result.Append(@"\\"); 
                    result.Append(owner.MachineName);
                    result.Append(@"\"); 
                    result.Append(fileName[0]);
                    result.Append("$");
                    result.Append(fileName, 2, fileName.Length - 2);
                    return result.ToString(); 

                } 
                else 
                    return null;
            } 
            else {
                // no need to expand environment variables, since this is done automatically by RegistryKey.GetValue()
                return fileName;
            } 
        }
 
 
        private short ShortFrom(byte[] buf, int offset) {
            // assumes little Endian byte order. 
            return(short) ((0xFF00 & (buf[offset+1] << 8)) | (0xFF & buf[offset]));
        }

        ///  
        /// 
        ///  
        /// Saves an entry as a stream of data. 
        /// 
        ///  
        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) {
            int len = IntFrom(dataBuf, bufOffset + FieldOffsets.LENGTH);
            byte[] buf = new byte[len];
            Array.Copy(dataBuf, bufOffset, buf, 0, len); 

            info.AddValue("DataBuffer", buf, typeof(byte[])); 
            info.AddValue("LogName", owner.Log); 
            info.AddValue("MachineName", owner.MachineName);
        } 

        /// 
        ///     Stores the offsets from the beginning of the record to fields within the record.
        ///  
        private static class FieldOffsets {
            /** int */ 
            internal const int LENGTH = 0; 
            /** int */
            internal const int RESERVED = 4; 
            /** int */
            internal const int RECORDNUMBER = 8;
            /** int */
            internal const int TIMEGENERATED = 12; 
            /** int */
            internal const int TIMEWRITTEN = 16; 
            /** int */ 
            internal const int EVENTID = 20;
            /** short */ 
            internal const int EVENTTYPE = 24;
            /** short */
            internal const int NUMSTRINGS = 26;
            /** short */ 
            internal const int EVENTCATEGORY = 28;
            /** short */ 
            internal const int RESERVEDFLAGS = 30; 
            /** int */
            internal const int CLOSINGRECORDNUMBER = 32; 
            /** int */
            internal const int STRINGOFFSET = 36;
            /** int */
            internal const int USERSIDLENGTH = 40; 
            /** int */
            internal const int USERSIDOFFSET = 44; 
            /** int */ 
            internal const int DATALENGTH = 48;
            /** int */ 
            internal const int DATAOFFSET = 52;
            /** bytes */
            internal const int RAWDATA = 56;
        } 

        // times in the struct are # seconds from midnight 1/1/1970. 
        private static readonly DateTime beginningOfTime = new DateTime(1970, 1, 1, 0, 0, 0); 

        // offsets in the struct are specified from the beginning, but we have to reference 
        // them from the beginning of the array.  This is the size of the members before that.
        private const int OFFSETFIXUP = 4+4+4+4+4+4+2+2+2+2+4+4+4+4+4+4;

    } 
}
                        

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