New test.
[mono.git] / mcs / class / System / System.Diagnostics / EventLog.cs
index d8160687f4983cae71dbf14d3953a1b888272ca6..4d6a29b831c54fd3e8534931c9a9e424d47b7c29 100644 (file)
@@ -2,13 +2,14 @@
 // System.Diagnostics.EventLog.cs
 //
 // Authors:
-//   Jonathan Pryor (jonpryor@vt.edu)
-//   Andreas Nahr (ClassDevelopment@A-SoftTech.com)
+//     Jonathan Pryor (jonpryor@vt.edu)
+//     Andreas Nahr (ClassDevelopment@A-SoftTech.com)
+//     Gert Driesen (drieseng@users.sourceforge.net)
 //
-// (C) 2002
-// (C) 2003 Andreas Nahr
+// Copyright (C) 2002
+// Copyright (C) 2003 Andreas Nahr
+// Copyright (C) 2006 Novell, Inc (http://www.novell.com)
 //
-
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -38,8 +39,6 @@ using System.ComponentModel.Design;
 using System.Globalization;
 using System.IO;
 
-using Microsoft.Win32;
-
 namespace System.Diagnostics 
 {
        [DefaultEvent ("EntryWritten")]
@@ -53,15 +52,20 @@ namespace System.Diagnostics
                private bool doRaiseEvents = false;
                private ISynchronizeInvoke synchronizingObject = null;
 
+               // IMPORTANT: also update constants in EventLogTest
+               internal const string LOCAL_FILE_IMPL = "local";
+               private const string WIN32_IMPL = "win32";
+               private const string NULL_IMPL = "null";
+
+               internal const string EVENTLOG_TYPE_VAR = "MONO_EVENTLOG_TYPE";
+
                private EventLogImpl Impl;
 
-               public EventLog()
-                       : this (string.Empty)
+               public EventLog() : this (string.Empty)
                {
                }
 
-               public EventLog(string logName)
-                       : this (logName, ".")
+               public EventLog(string logName) : this (logName, ".")
                {
                }
 
@@ -76,22 +80,21 @@ namespace System.Diagnostics
                                throw new ArgumentNullException ("logName");
                        }
                        if (machineName == null || machineName.Length == 0)
+#if NET_2_0
                                throw new ArgumentException (string.Format (
                                        CultureInfo.InvariantCulture, "Invalid value '{0}' for"
                                        + " parameter 'machineName'.", machineName));
+#else
+                               throw new ArgumentException (string.Format (
+                                       CultureInfo.InvariantCulture, "Invalid value {0} for"
+                                       + " parameter MachineName.", machineName));
+#endif
 
                        this.source = source;
                        this.machineName = machineName;
                        this.logName = logName;
 
-                       Impl = new NullEventLog (this);
-                       /*
-                       if (Win32EventLogEnabled) {
-                               Impl = new Win32EventLog (this);
-                       } else {
-                               Impl = new UnixEventLog (this);
-                       }
-                       */
+                       Impl = CreateEventLogImpl (this);
                        Impl.EntryWritten += new EntryWrittenEventHandler (EntryWrittenHandler);
                }
 
@@ -157,27 +160,37 @@ namespace System.Diagnostics
                        set {synchronizingObject = value;}
                }
 
-               public void BeginInit()
+               public void BeginInit ()
                {
                        Impl.BeginInit();
                }
 
-               public void Clear()
+               public void Clear ()
                {
-                       Impl.Clear();
+                       string logName = Log;
+                       if (logName == null || logName.Length == 0)
+                               throw new ArgumentException ("Log property value has not been specified.");
+
+                       if (!EventLog.Exists (logName, MachineName))
+                               throw new InvalidOperationException (string.Format (
+                                       CultureInfo.InvariantCulture, "Event Log '{0}'"
+                                       + " does not exist on computer '{1}'.", logName,
+                                       machineName));
+
+                       Impl.Clear ();
                }
 
-               public void Close()
+               public void Close ()
                {
                        Impl.Close();
                }
 
-               public static void CreateEventSource(string source, string logName)
+               public static void CreateEventSource (string source, string logName)
                {
                        CreateEventSource (source, logName, ".");
                }
 
-               public static void CreateEventSource(string source, 
+               public static void CreateEventSource (string source, 
                        string logName, 
                        string machineName)
                {
@@ -193,74 +206,23 @@ namespace System.Diagnostics
 #endif
                static void CreateEventSource (EventSourceCreationData sourceData)
                {
-                       if (sourceData.Source == null || sourceData.Source.Length == 0) {
-                               throw new ArgumentException ("Source is not set");
-                       }
-                       if (sourceData.LogName == null || sourceData.LogName.Length == 0) {
-                               throw new ArgumentException ("LogName is not set");
-                       }
+                       if (sourceData.Source == null || sourceData.Source.Length == 0)
+                               throw new ArgumentException ("Source property value has not been specified.");
 
-                       if (SourceExists (sourceData.Source, sourceData.MachineName)) {
+                       if (sourceData.LogName == null || sourceData.LogName.Length == 0)
+                               throw new ArgumentException ("Log property value has not been specified.");
+
+                       if (SourceExists (sourceData.Source, sourceData.MachineName))
                                throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
                                        "Source '{0}' already exists on '{1}'.", sourceData.Source,
                                        sourceData.MachineName));
-                       }
 
-                       using (RegistryKey eventLogKey = GetEventLogKey (sourceData.MachineName, true)) {
-                               if (eventLogKey == null)
-                                       throw new InvalidOperationException ("EventLog registry key is missing.");
-
-                               bool logKeyCreated = false;
-                               RegistryKey logKey = null;
-                               try {
-                                       logKey = eventLogKey.OpenSubKey (sourceData.LogName, true);
-                                       if (logKey == null) {
-                                               logKey = eventLogKey.CreateSubKey (sourceData.LogName);
-                                               logKey.SetValue ("Sources", new string[] { sourceData.LogName,
-                                                       sourceData.Source });
-                                               UpdateLogRegistry (logKey);
-
-                                               using (RegistryKey sourceKey = logKey.CreateSubKey (sourceData.LogName)) {
-                                                       UpdateSourceRegistry (sourceKey, sourceData);
-                                               }
-
-                                               logKeyCreated = true;
-                                       }
-
-                                       if (sourceData.LogName != sourceData.Source) {
-                                               if (!logKeyCreated) {
-                                                       string[] sources = (string[]) logKey.GetValue ("Sources");
-                                                       if (sources == null) {
-                                                               logKey.SetValue ("Sources", new string[] { sourceData.LogName,
-                                                                       sourceData.Source });
-                                                       } else {
-                                                               bool found = false;
-                                                               for (int i = 0; i < sources.Length; i++) {
-                                                                       if (sources[i] == sourceData.Source) {
-                                                                               found = true;
-                                                                               break;
-                                                                       }
-                                                               }
-                                                               if (!found) {
-                                                                       string[] newSources = new string[sources.Length + 1];
-                                                                       Array.Copy (sources, 0, newSources, 0, sources.Length);
-                                                                       newSources[sources.Length] = sourceData.Source;
-                                                                       logKey.SetValue ("Sources", newSources);
-                                                               }
-                                                       }
-                                               }
-                                               using (RegistryKey sourceKey = logKey.CreateSubKey (sourceData.Source)) {
-                                                       UpdateSourceRegistry (sourceKey, sourceData);
-                                               }
-                                       }
-                               } finally {
-                                       if (logKey != null)
-                                               logKey.Close ();
-                               }
-                       }
+                       EventLogImpl impl = CreateEventLogImpl (sourceData.LogName,
+                               sourceData.MachineName, sourceData.Source);
+                       impl.CreateEventSource (sourceData);
                }
 
-               public static void Delete(string logName)
+               public static void Delete (string logName)
                {
                        Delete (logName, ".");
                }
@@ -275,38 +237,12 @@ namespace System.Diagnostics
                        if (logName == null || logName.Length == 0)
                                throw new ArgumentException ("Log to delete was not specified.");
 
-                       using (RegistryKey eventLogKey = GetEventLogKey (machineName, true)) {
-                               if (eventLogKey == null)
-                                       throw new InvalidOperationException ("The event log key does not exist.");
-
-                               using (RegistryKey logKey = eventLogKey.OpenSubKey (logName, false)) {
-                                       if (logKey == null)
-                                               throw new InvalidOperationException (string.Format (
-                                                       CultureInfo.InvariantCulture, "Event Log '{0}'"
-                                                       + " does not exist on computer '{1}'.", logName,
-                                                       machineName));
-
-                                       // remove all eventlog entries for specified log
-                                       using (EventLog eventLog = new EventLog (logName, machineName)) {
-                                               eventLog.Clear ();
-                                       }
-
-                                       // remove file holding event log entries
-                                       string file = (string) logKey.GetValue ("File");
-                                       if (file != null) {
-                                               try {
-                                                       File.Delete (file);
-                                               } catch (Exception) {
-                                                       // .NET seems to ignore failures here
-                                               }
-                                       }
-                               }
-
-                               eventLogKey.DeleteSubKeyTree (logName);
-                       }
+                       EventLogImpl impl = CreateEventLogImpl (logName, machineName, 
+                               string.Empty);
+                       impl.Delete (logName, machineName);
                }
 
-               public static void DeleteEventSource(string source)
+               public static void DeleteEventSource (string source)
                {
                        DeleteEventSource (source, ".");
                }
@@ -315,35 +251,25 @@ namespace System.Diagnostics
                public static void DeleteEventSource (string source, string machineName)
                {
                        if (machineName == null || machineName.Length == 0)
+#if NET_2_0
                                throw new ArgumentException (string.Format (
                                        CultureInfo.InvariantCulture, "Invalid value '{0}' for"
                                        + " parameter 'machineName'.", machineName));
+#else
+                               throw new ArgumentException (string.Format (
+                                       CultureInfo.InvariantCulture, "Invalid value {0} for"
+                                       + " parameter machineName.", machineName));
+#endif
 
-                       using (RegistryKey logKey = FindLogKeyBySource (source, machineName, true)) {
-                               if (logKey == null) {
-                                       throw new ArgumentException (string.Format (
-                                               CultureInfo.InvariantCulture, "The source '{0}' is not"
-                                               + " registered on computer '{1}'.", source, machineName));
-                               }
-
-                               logKey.DeleteSubKeyTree (source);
-
-                               string[] sources = (string[]) logKey.GetValue ("Sources");
-                               if (sources != null) {
-                                       ArrayList temp = new ArrayList ();
-                                       for (int i = 0; i < sources.Length; i++)
-                                               if (sources[i] != source)
-                                                       temp.Add (sources[i]);
-                                       string[] newSources = new string[temp.Count];
-                                       temp.CopyTo (newSources, 0);
-                                       logKey.SetValue ("Sources", newSources);
-                               }
-                       }
+                       EventLogImpl impl = CreateEventLogImpl (string.Empty, machineName,
+                               source);
+                       impl.DeleteEventSource (source, machineName);
                }
 
                protected override void Dispose (bool disposing)
                {
-                       Impl.Dispose (disposing);
+                       if (Impl != null)
+                               Impl.Dispose (disposing);
                }
 
                public void EndInit()
@@ -351,7 +277,7 @@ namespace System.Diagnostics
                        Impl.EndInit();
                }
 
-               public static bool Exists(string logName)
+               public static bool Exists (string logName)
                {
                        return Exists (logName, ".");
                }
@@ -359,9 +285,15 @@ namespace System.Diagnostics
                [MonoTODO ("Support remote machine")]
                public static bool Exists (string logName, string machineName)
                {
-                       using (RegistryKey logKey = FindLogKeyByName (logName, machineName, false)) {
-                               return (logKey != null);
-                       }
+                       if (machineName == null || machineName.Length == 0)
+                               throw new ArgumentException ("Invalid format for argument machineName.");
+
+                       if (logName == null || logName.Length == 0)
+                               return false; 
+
+                       EventLogImpl impl = CreateEventLogImpl (logName, machineName,
+                               string.Empty);
+                       return impl.Exists (logName, machineName);
                }
 
                public static EventLog[] GetEventLogs ()
@@ -372,32 +304,30 @@ namespace System.Diagnostics
                [MonoTODO ("Support remote machine")]
                public static EventLog[] GetEventLogs (string machineName)
                {
-                       using (RegistryKey eventLogKey = GetEventLogKey (machineName, false)) {
-                               if (eventLogKey == null) {
-                                       throw new InvalidOperationException ("TODO");
-                               }
-                               string[] logNames = eventLogKey.GetSubKeyNames ();
-                               EventLog[] eventLogs = new EventLog[logNames.Length];
-                               for (int i = 0; i < logNames.Length; i++) {
-                                       EventLog eventLog = new EventLog (logNames[i], machineName);
-                                       eventLogs[i] = eventLog;
-                               }
-                               return eventLogs;
-                       }
+                       EventLogImpl impl = CreateEventLogImpl (new EventLog ());
+                       return impl.GetEventLogs (machineName);
                }
 
                [MonoTODO ("Support remote machine")]
                public static string LogNameFromSourceName (string source, string machineName)
                {
-                       using (RegistryKey logKey = FindLogKeyBySource (source, machineName, false)) {
-                               if (logKey == null)
-                                       return string.Empty;
+                       if (machineName == null || machineName.Length == 0)
+#if NET_2_0
+                               throw new ArgumentException (string.Format (
+                                       CultureInfo.InvariantCulture, "Invalid value '{0}' for"
+                                       + " parameter 'MachineName'.", machineName));
+#else
+                               throw new ArgumentException (string.Format (
+                                       CultureInfo.InvariantCulture, "Invalid value {0} for"
+                                       + " parameter MachineName.", machineName));
+#endif
 
-                               return GetLogName (logKey);
-                       }
+                       EventLogImpl impl = CreateEventLogImpl (string.Empty, machineName,
+                               source);
+                       return impl.LogNameFromSourceName (source, machineName);
                }
 
-               public static bool SourceExists(string source)
+               public static bool SourceExists (string source)
                {
                        return SourceExists (source, ".");
                }
@@ -410,80 +340,66 @@ namespace System.Diagnostics
                                        CultureInfo.InvariantCulture, "Invalid value '{0}' for"
                                        + " parameter 'machineName'.", machineName));
 
-                       RegistryKey logKey = FindLogKeyBySource (source, machineName, false);
-                       if (logKey != null) {
-                               logKey.Close ();
-                               return true;
-                       }
-                       return false;
+                       EventLogImpl impl = CreateEventLogImpl (string.Empty, machineName,
+                               source);
+                       return impl.SourceExists (source, machineName);
                }
 
-               public void WriteEntry(string message)
+               public void WriteEntry (string message)
                {
                        WriteEntry (message, EventLogEntryType.Information);
                }
 
-               public void WriteEntry(string message, EventLogEntryType type)
+               public void WriteEntry (string message, EventLogEntryType type)
                {
                        WriteEntry (message, type, 0);
                }
 
-               public void WriteEntry(string message, EventLogEntryType type, 
+               public void WriteEntry (string message, EventLogEntryType type, 
                        int eventID)
                {
                        WriteEntry (message, type, eventID, 0);
                }
 
-               public void WriteEntry(string message, EventLogEntryType type, 
+               public void WriteEntry (string message, EventLogEntryType type, 
                        int eventID,
                        short category)
                {
-                       if (Source.Length == 0) {
-                               throw new ArgumentException ("Source property was not set"
-                                       + "before writing to the event log.");
-                       }
-
-                       if (!SourceExists (Source, MachineName)) {
-                               if (Log == null || Log.Length == 0) {
-                                       Log = "Application";
-                               }
-                               CreateEventSource (Source, Log, MachineName);
-                       }
-
                        WriteEntry (message, type, eventID, category, null);
                }
 
-               public void WriteEntry(string message, EventLogEntryType type, 
+               public void WriteEntry (string message, EventLogEntryType type, 
                        int eventID,
                        short category, byte[] rawData)
                {
-                       Impl.WriteEntry (message, type, eventID, category, rawData);
+                       WriteEntry (new string [] { message }, type, eventID,
+                               category, rawData);
                }
 
-               public static void WriteEntry(string source, string message)
+               public static void WriteEntry (string source, string message)
                {
                        WriteEntry (source, message, EventLogEntryType.Information);
                }
 
-               public static void WriteEntry(string source, string message, 
+               public static void WriteEntry (string source, string message, 
                        EventLogEntryType type)
                {
-                       WriteEntry (source, message, EventLogEntryType.Information, 0);
+                       WriteEntry (source, message, type, 0);
                }
 
-               public static void WriteEntry(string source, string message, 
+               public static void WriteEntry (string source, string message, 
                        EventLogEntryType type, int eventID)
                {
-                       WriteEntry (source, message, EventLogEntryType.Information, eventID, 0);
+                       WriteEntry (source, message, type, eventID, 0);
                }
 
-               public static void WriteEntry(string source, string message, 
+               public static void WriteEntry (string source, string message, 
                        EventLogEntryType type, int eventID, short category)
                {
-                       WriteEntry (source, message, EventLogEntryType.Information, eventID, category, null);
+                       WriteEntry (source, message, type, eventID, category, null);
                }
 
-               public static void WriteEntry(string source, string message, 
+               public static void WriteEntry (string source, string message, 
                        EventLogEntryType type, int eventID, short category, 
                        byte[] rawData)
                {
@@ -493,6 +409,49 @@ namespace System.Diagnostics
                        }
                }
 
+#if NET_2_0
+               public void WriteEvent (EventInstance instance, params object [] values)
+               {
+                       WriteEvent (instance, null, values);
+               }
+
+               public void WriteEvent (EventInstance instance, byte [] data, params object [] values)
+               {
+                       if (instance == null)
+                               throw new ArgumentNullException ("instance");
+
+                       string [] replacementStrings = null;
+                       if (values != null) {
+                               replacementStrings = new string [values.Length];
+                               for (int i = 0; i < values.Length; i++) {
+                                       object value = values [i];
+                                       if (value == null)
+                                               replacementStrings [i] = string.Empty;
+                                       else
+                                               replacementStrings [i] = values [i].ToString ();
+                               }
+                       } else {
+                               replacementStrings = new string [0];
+                       }
+
+                       WriteEntry (replacementStrings, instance.EntryType, instance
+                               .InstanceId, (short) instance.CategoryId, data);
+               }
+
+               public static void WriteEvent (string source, EventInstance instance, params object [] values)
+               {
+                       WriteEvent (source, instance, null, values);
+               }
+
+               public static void WriteEvent (string source, EventInstance instance, byte [] data, params object [] values)
+               {
+                       using (EventLog eventLog = new EventLog ()) {
+                               eventLog.Source = source;
+                               eventLog.WriteEvent (instance, data, values);
+                       }
+               }
+#endif
+
                internal void OnEntryWritten (EventLogEntry newEntry)
                {
                        if (EntryWritten != null)
@@ -500,6 +459,7 @@ namespace System.Diagnostics
                }
 
                [MonitoringDescription ("Raised for each EventLog entry written.")]
+               [MonoTODO ("Use FSM for local file implementation, and NotifyChangeEventLog for win32")]
                public event EntryWrittenEventHandler EntryWritten;
 
                internal string GetLogName ()
@@ -512,105 +472,124 @@ namespace System.Diagnostics
                        return logName;
                }
 
+               private static EventLogImpl CreateEventLogImpl (string logName, string machineName, string source)
+               {
+                       EventLog eventLog = new EventLog (logName, machineName, source);
+                       return CreateEventLogImpl (eventLog);
+               }
+
+               private static EventLogImpl CreateEventLogImpl (EventLog eventLog)
+               {
+                       switch (EventLogImplType) {
+                       case LOCAL_FILE_IMPL:
+                               return new LocalFileEventLog (eventLog);
+                       case WIN32_IMPL:
+                               return new Win32EventLog (eventLog);
+                       case NULL_IMPL:
+                               return new NullEventLog (eventLog);
+                       default:
+                               // we should never get here
+                               throw new NotSupportedException (string.Format (
+                                       CultureInfo.InvariantCulture, "Eventlog implementation"
+                                       + " '{0}' is not supported.", EventLogImplType));
+                       }
+               }
+
                private static bool Win32EventLogEnabled {
                        get {
                                return (Environment.OSVersion.Platform == PlatformID.Win32NT);
                        }
                }
 
-               private static void UpdateLogRegistry (RegistryKey logKey)
+               // IMPORTANT: also modify corresponding property in EventLogTest
+               private static string EventLogImplType
                {
-                       if (!Win32EventLogEnabled)
-                               return;
-
-                       // TODO: write other Log values:
-                       // - MaxSize
-                       // - Retention
-                       // - AutoBackupLogFiles
-
-                       if (logKey.GetValue ("File") == null) {
-                               string logName = GetLogName (logKey);
-                               string file;
-                               if (logName.Length > 8) {
-                                       file = logName.Substring (0, 8) + ".evt";
+                       get {
+                               string implType = Environment.GetEnvironmentVariable (EVENTLOG_TYPE_VAR);
+                               if (implType == null) {
+                                       if (Win32EventLogEnabled)
+                                               return WIN32_IMPL;
+                                       implType = NULL_IMPL;
                                } else {
-                                       file = logName + ".evt";
+                                       if (Win32EventLogEnabled && string.Compare (implType, WIN32_IMPL, true) == 0)
+                                               implType = WIN32_IMPL;
+                                       else if (string.Compare (implType, NULL_IMPL, true) == 0)
+                                               implType = NULL_IMPL;
+                                       else if (string.Compare (implType, 0, LOCAL_FILE_IMPL, 0, LOCAL_FILE_IMPL.Length, true) == 0)
+                                               implType = LOCAL_FILE_IMPL;
+                                       else
+                                               throw new NotSupportedException (string.Format (
+                                                       CultureInfo.InvariantCulture, "Eventlog implementation"
+                                                       + " '{0}' is not supported.", implType));
                                }
-                               string configPath = Path.Combine (Environment.GetFolderPath (
-                                       Environment.SpecialFolder.System), "config");
-                               logKey.SetValue ("File", Path.Combine (configPath, file));
+                               return implType;
                        }
-
                }
 
-               private static void UpdateSourceRegistry (RegistryKey sourceKey, EventSourceCreationData data)
+               private void WriteEntry (string [] replacementStrings, EventLogEntryType type, long instanceID, short category, byte [] rawData)
                {
-                       if (data.CategoryCount > 0)
-                               sourceKey.SetValue ("CategoryCount", data.CategoryCount);
+                       if (Source.Length == 0)
+                               throw new ArgumentException ("Source property was not set"
+                                       + "before writing to the event log.");
 
-                       if (data.CategoryResourceFile != null && data.CategoryResourceFile.Length > 0)
-                               sourceKey.SetValue ("CategoryMessageFile", data.CategoryResourceFile);
+                       if (!Enum.IsDefined (typeof (EventLogEntryType), type))
+                               throw new InvalidEnumArgumentException ("type", (int) type,
+                                       typeof (EventLogEntryType));
 
-                       if (data.MessageResourceFile != null && data.MessageResourceFile.Length > 0)
-                               sourceKey.SetValue ("EventMessageFile", data.MessageResourceFile);
+#if NET_2_0
+                       ValidateEventID (instanceID);
+#endif
 
-                       if (data.ParameterResourceFile != null && data.ParameterResourceFile.Length > 0)
-                               sourceKey.SetValue ("ParameterMessageFile", data.ParameterResourceFile);
-               }
+                       if (!SourceExists (Source, MachineName)) {
+                               if (Log == null || Log.Length == 0) {
+                                       Log = "Application";
+                               }
+                               CreateEventSource (Source, Log, MachineName);
+
+#if ONLY_1_1
+                               ValidateEventID (instanceID);
+#endif
+                       } else if (logName != null && logName.Length != 0) {
+#if ONLY_1_1
+                               ValidateEventID (instanceID);
+#endif
+                               string actualLog = LogNameFromSourceName (Source, MachineName);
+                               if (string.Compare (logName, actualLog, true, CultureInfo.InvariantCulture) != 0)
+                                       throw new ArgumentException (string.Format (
+                                               CultureInfo.InvariantCulture, "The source '{0}' is not"
+                                               + " registered in log '{1}' (it is registered in log"
+                                               + " '{2}'). The Source and Log properties must be"
+                                               + " matched, or you may set Log to the empty string,"
+                                               + " and it will automatically be matched to the Source"
+                                               + " property.", Source, logName, actualLog));
+                       }
 
-               private static string GetLogName (RegistryKey logKey) {
-                       string logName = logKey.Name;
-                       return logName.Substring (logName.LastIndexOf ("\\") + 1);
+#if ONLY_1_1
+                       ValidateEventID (instanceID);
+#endif
+
+                       if (rawData == null)
+                               rawData = new byte [0];
+
+                       Impl.WriteEntry (replacementStrings, type, (uint) instanceID, category, rawData);
                }
 
-               [MonoTODO ("Support remote machines")]
-               private static RegistryKey GetEventLogKey (string machineName, bool writable)
+               private void ValidateEventID (long instanceID)
                {
-                       return Registry.LocalMachine.OpenSubKey (@"SYSTEM\CurrentControlSet\Services\EventLog", writable);
+                       int eventID = GetEventID (instanceID);
+                       if (eventID < ushort.MinValue || eventID > ushort.MaxValue)
+                               throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
+                                       "Invalid eventID value '{0}'. It must be in the range between"
+                                       + " '{1}' and '{2}'.", instanceID, ushort.MinValue, ushort.MaxValue));
                }
 
-               private static RegistryKey FindLogKeyByName (string logName, string machineName, bool writable)
+               internal static int GetEventID (long instanceID)
                {
-                       using (RegistryKey eventLogKey = GetEventLogKey (machineName, writable)) {
-                               if (eventLogKey == null) {
-                                       return null;
-                               }
+                       long inst = (instanceID < 0) ? -instanceID : instanceID;
 
-                               return eventLogKey.OpenSubKey (logName, writable);
-                       }
-               }
-
-               private static RegistryKey FindLogKeyBySource (string source, string machineName, bool writable)
-               {
-                       if (source == null || source.Length == 0)
-                               return null;
-
-                       RegistryKey eventLogKey = null;
-                       try {
-                               eventLogKey = GetEventLogKey (machineName, writable);
-                               if (eventLogKey == null)
-                                       return null;
-
-                               string[] subKeys = eventLogKey.GetSubKeyNames ();
-                               for (int i = 0; i < subKeys.Length; i++) {
-                                       RegistryKey sourceKey = null;
-                                       try {
-                                               RegistryKey logKey = eventLogKey.OpenSubKey (subKeys[i], writable);
-                                               if (logKey != null) {
-                                                       sourceKey = logKey.OpenSubKey (source, writable);
-                                                       if (sourceKey != null)
-                                                               return logKey;
-                                               }
-                                       } finally {
-                                               if (sourceKey != null)
-                                                       sourceKey.Close ();
-                                       }
-                               }
-                               return null;
-                       } finally {
-                               if (eventLogKey != null)
-                                       eventLogKey.Close ();
-                       }
+                       // MSDN: eventID equals the InstanceId with the top two bits masked
+                       int eventID = (int) (inst & 0x3fffffff);
+                       return (instanceID < 0) ? -eventID : eventID;
                }
        }
 }