File: System\Diagnostics\Eventing\Reader\EventLogRecord.cs
Project: ndp\fx\src\Core\System.Core.csproj (System.Core)
// ==++==
// 
//   Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// ==--==
/*============================================================
**
** Class: EventLogRecord
**
** Purpose: 
** This public class is an EventLog implementation of EventRecord.  An
** instance of this is obtained from an EventLogReader.
**
============================================================*/
 
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Security.Permissions;
using Microsoft.Win32;
 
namespace System.Diagnostics.Eventing.Reader {
 
    [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
    public class EventLogRecord : EventRecord {
 
        private const int SYSTEM_PROPERTY_COUNT = 18;
 
        //
        // access to the data member reference is safe, while 
        // invoking methods on it is marked SecurityCritical as appropriate.
        //
        [System.Security.SecuritySafeCritical]
        private EventLogHandle handle;
 
        private EventLogSession session;
 
        private NativeWrapper.SystemProperties systemProperties;
        private string containerChannel;
        private int[] matchedQueryIds;
 
        //a dummy object which is used only for the locking.
        object syncObject;
 
        //cached DisplayNames for each instance
        private string levelName = null;
        private string taskName = null;
        private string opcodeName = null;
        private IEnumerable<string> keywordsNames = null;
 
        //cached DisplayNames for each instance
        private bool levelNameReady;
        private bool taskNameReady;
        private bool opcodeNameReady;
 
        private ProviderMetadataCachedInformation cachedMetadataInformation;
 
        // marking as TreatAsSafe because just passing around a reference to an EventLogHandle is safe.
        [System.Security.SecuritySafeCritical]
        internal EventLogRecord(EventLogHandle handle, EventLogSession session, ProviderMetadataCachedInformation cachedMetadataInfo) {
            this.cachedMetadataInformation = cachedMetadataInfo;
            this.handle = handle;
            this.session = session;
            systemProperties = new NativeWrapper.SystemProperties();
            syncObject = new object();
        }
 
        internal EventLogHandle Handle {
            // just returning reference to security critical type, the methods
            // of that type are protected by SecurityCritical as appropriate.
            [System.Security.SecuritySafeCritical]
            get {
                return handle;
            }
        }
 
 
        internal void PrepareSystemData() {
 
            if (this.systemProperties.filled)
                return;
 
            //prepare the System Context, if it is not already initialized.
            this.session.SetupSystemContext();
 
            lock (this.syncObject) {
                if (this.systemProperties.filled == false) {
                    NativeWrapper.EvtRenderBufferWithContextSystem(this.session.renderContextHandleSystem, this.handle, UnsafeNativeMethods.EvtRenderFlags.EvtRenderEventValues, this.systemProperties, SYSTEM_PROPERTY_COUNT);
                    this.systemProperties.filled = true;
                }
            }
        }
 
        public override int Id {
            get {
                PrepareSystemData();
                if (this.systemProperties.Id == null)
                    return 0;
                return (int)this.systemProperties.Id;
            }
        }
 
        public override byte? Version {
            get {
                PrepareSystemData();
                return this.systemProperties.Version;
            }
        }
 
        public override int? Qualifiers {
            get {
                PrepareSystemData();
                return (int?)(uint?)this.systemProperties.Qualifiers;
            }
        }
 
        public override byte? Level {
            get {
                PrepareSystemData();
                return this.systemProperties.Level;
            }
        }
 
        public override int? Task {
            get {
                PrepareSystemData();
                return (int?)(uint?)this.systemProperties.Task;
            }
        }
 
        public override short? Opcode {
            get {
                PrepareSystemData();
                return (short?)(ushort?)this.systemProperties.Opcode;
            }
        }
 
        public override long? Keywords {
            get {
                PrepareSystemData();
                return (long?)this.systemProperties.Keywords;
            }
        }
 
        public override long? RecordId {
            get {
                PrepareSystemData();
                return (long?)this.systemProperties.RecordId;
            }
        }
 
        public override string ProviderName {
            get {
                PrepareSystemData();
                return this.systemProperties.ProviderName;
            }
        }
 
        public override Guid? ProviderId {
            get {
                PrepareSystemData();
                return this.systemProperties.ProviderId;
            }
        }
 
        public override string LogName {
            get {
                PrepareSystemData();
                return this.systemProperties.ChannelName;
            }
        }
 
        public override int? ProcessId {
            get {
                PrepareSystemData();
                return (int?)this.systemProperties.ProcessId;
            }
        }
 
        public override int? ThreadId {
            get {
                PrepareSystemData();
                return (int?)this.systemProperties.ThreadId;
            }
        }
 
        public override string MachineName {
            get {
                PrepareSystemData();
                return this.systemProperties.ComputerName;
            }
        }
 
        public override System.Security.Principal.SecurityIdentifier UserId {
            get {
                PrepareSystemData();
                return this.systemProperties.UserId;
            }
        }
 
        public override DateTime? TimeCreated {
            get {
                PrepareSystemData();
                return this.systemProperties.TimeCreated;
            }
        }
 
        public override Guid? ActivityId {
            get {
                PrepareSystemData();
                return this.systemProperties.ActivityId;
            }
        }
 
        public override Guid? RelatedActivityId {
            get {
                PrepareSystemData();
                return this.systemProperties.RelatedActivityId;
            }
        }
 
        public string ContainerLog {
            get {
                if (this.containerChannel != null)
                    return this.containerChannel;
                lock (this.syncObject) {
                    if (this.containerChannel == null) {
                        this.containerChannel = (string)NativeWrapper.EvtGetEventInfo(this.Handle, UnsafeNativeMethods.EvtEventPropertyId.EvtEventPath);
                    }
                    return this.containerChannel;
                }
            }
        }
 
        public IEnumerable<int> MatchedQueryIds {
            get {
                if (this.matchedQueryIds != null)
                    return this.matchedQueryIds;
                lock (this.syncObject) {
                    if (this.matchedQueryIds == null) {
                        this.matchedQueryIds = (int[])NativeWrapper.EvtGetEventInfo(this.Handle, UnsafeNativeMethods.EvtEventPropertyId.EvtEventQueryIDs);
                    }
                    return this.matchedQueryIds;
                }
            }
        }
 
        
        public override EventBookmark Bookmark {
            [System.Security.SecuritySafeCritical]
            get {
                EventLogPermissionHolder.GetEventLogPermission().Demand();
 
                EventLogHandle bookmarkHandle = NativeWrapper.EvtCreateBookmark(null);
                NativeWrapper.EvtUpdateBookmark(bookmarkHandle, this.handle);
                string bookmarkText = NativeWrapper.EvtRenderBookmark(bookmarkHandle);
 
                return new EventBookmark(bookmarkText);
            }
        }
 
        public override string FormatDescription() {
 
            return this.cachedMetadataInformation.GetFormatDescription(this.ProviderName, this.handle);
        }
 
        public override string FormatDescription(IEnumerable<object> values) {
            if (values == null) return this.FormatDescription();
 
            //copy the value IEnumerable to an array.
            string[] theValues = new string[0];
            int i = 0;
            foreach (object o in values) {
                if ( theValues.Length == i )
                    Array.Resize( ref theValues, i+1 );
                theValues[i] = o.ToString();
                i++;
            } 
 
            return this.cachedMetadataInformation.GetFormatDescription(this.ProviderName, this.handle, theValues);
        }
 
        public override string LevelDisplayName {
            get {
                if ( this.levelNameReady )
                    return this.levelName;
                lock (this.syncObject) {
                    if (this.levelNameReady == false) {
                        this.levelNameReady = true;
                        this.levelName = this.cachedMetadataInformation.GetLevelDisplayName(this.ProviderName, this.handle);
                    }
                    return this.levelName;
                }
            }
        }
 
 
        public override string OpcodeDisplayName {
            get {
                lock (this.syncObject) {
                    if (this.opcodeNameReady == false) {
                        this.opcodeNameReady = true;
                        this.opcodeName = this.cachedMetadataInformation.GetOpcodeDisplayName(this.ProviderName, this.handle);
 
                    }
                    return this.opcodeName;
                }
            }
        }
 
        public override string TaskDisplayName {
            get {
                if (this.taskNameReady == true)
                    return this.taskName;
                lock (this.syncObject) {
                    if (this.taskNameReady == false) {
                        this.taskNameReady = true;
                        this.taskName = this.cachedMetadataInformation.GetTaskDisplayName(this.ProviderName, this.handle);
                    }
                    return this.taskName;
                }
            }
        }
 
        public override IEnumerable<string> KeywordsDisplayNames {
            get {
                if (this.keywordsNames != null)
                    return this.keywordsNames;
                lock (this.syncObject) {
                    if (this.keywordsNames == null) {
                        this.keywordsNames = this.cachedMetadataInformation.GetKeywordDisplayNames(this.ProviderName, this.handle);
                    }
                    return this.keywordsNames;
                }
            }
        }
 
 
        public override IList<EventProperty> Properties {
            get {
                this.session.SetupUserContext();
                IList<object> properties = NativeWrapper.EvtRenderBufferWithContextUserOrValues(this.session.renderContextHandleUser, this.handle);
                List<EventProperty> list = new List<EventProperty>();
                foreach (object value in properties) {
                    list.Add(new EventProperty(value));
                }
                return list;
            }
        }
 
        public IList<object> GetPropertyValues(EventLogPropertySelector propertySelector) {
            if (propertySelector == null)
                throw new ArgumentNullException("propertySelector");
            return NativeWrapper.EvtRenderBufferWithContextUserOrValues(propertySelector.Handle, this.handle);
        }
 
        // marked as SecurityCritical because it allocates SafeHandle
        // marked as TreatAsSafe because it performs Demand.
        [System.Security.SecuritySafeCritical]
        public override string ToXml() {
            EventLogPermissionHolder.GetEventLogPermission().Demand();
            StringBuilder renderBuffer = new StringBuilder(2000);
            NativeWrapper.EvtRender(EventLogHandle.Zero, this.handle, UnsafeNativeMethods.EvtRenderFlags.EvtRenderEventXml, renderBuffer);
            return renderBuffer.ToString();
        }
 
        [System.Security.SecuritySafeCritical]
        protected override void Dispose(bool disposing) {
            try {
 
                if (disposing) {
                    EventLogPermissionHolder.GetEventLogPermission().Demand();
                }
 
                if ( this.handle != null && !this.handle.IsInvalid )
                    this.handle.Dispose();
            }
            finally {
                base.Dispose(disposing);
            }
        }
 
        // marked as SecurityCritical because allocates SafeHandle.
        [System.Security.SecurityCritical]
        internal static EventLogHandle GetBookmarkHandleFromBookmark(EventBookmark bookmark) {
            if (bookmark == null)
                return EventLogHandle.Zero;
            EventLogHandle handle = NativeWrapper.EvtCreateBookmark(bookmark.BookmarkText);
            return handle;
        }
    }
 
}