Skip to content

Instantly share code, notes, and snippets.

@Iristyle
Created August 24, 2017 00:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Iristyle/fc3abc4a2daccdded5186869892c1ce0 to your computer and use it in GitHub Desktop.
Save Iristyle/fc3abc4a2daccdded5186869892c1ce0 to your computer and use it in GitHub Desktop.
.NET CreateEventSource code
[ResourceExposure(ResourceScope.None)]
[ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
public static void CreateEventSource(EventSourceCreationData sourceData) {
if (sourceData == null)
throw new ArgumentNullException("sourceData");
string logName = sourceData.LogName;
string source = sourceData.Source;
string machineName = sourceData.MachineName;
// verify parameters
Debug.WriteLineIf(CompModSwitches.EventLog.TraceVerbose, "CreateEventSource: Checking arguments");
if (!SyntaxCheck.CheckMachineName(machineName)) {
throw new ArgumentException(SR.GetString(SR.InvalidParameter, "machineName", machineName));
}
if (logName == null || logName.Length==0)
logName = "Application";
if (!ValidLogName(logName, false))
throw new ArgumentException(SR.GetString(SR.BadLogName));
if (source == null || source.Length==0)
throw new ArgumentException(SR.GetString(SR.MissingParameter, "source"));
if (source.Length + EventLogKey.Length > 254)
throw new ArgumentException(SR.GetString(SR.ParameterTooLong, "source", 254 - EventLogKey.Length));
EventLogPermission permission = new EventLogPermission(EventLogPermissionAccess.Administer, machineName);
permission.Demand();
Mutex mutex = null;
RuntimeHelpers.PrepareConstrainedRegions();
try {
SharedUtils.EnterMutex(eventLogMutexName, ref mutex);
Debug.WriteLineIf(CompModSwitches.EventLog.TraceVerbose, "CreateEventSource: Calling SourceExists");
if (SourceExists(source, machineName, true)) {
Debug.WriteLineIf(CompModSwitches.EventLog.TraceVerbose, "CreateEventSource: SourceExists returned true");
// don't let them register a source if it already exists
// this makes more sense than just doing it anyway, because the source might
// be registered under a different log name, and we don't want to create
// duplicates.
if (".".Equals(machineName))
throw new ArgumentException(SR.GetString(SR.LocalSourceAlreadyExists, source));
else
throw new ArgumentException(SR.GetString(SR.SourceAlreadyExists, source, machineName));
}
Debug.WriteLineIf(CompModSwitches.EventLog.TraceVerbose, "CreateEventSource: Getting DllPath");
//SECREVIEW: Note that EventLog permission is demanded above.
PermissionSet permissionSet = _UnsafeGetAssertPermSet();
permissionSet.Assert();
RegistryKey baseKey = null;
RegistryKey eventKey = null;
RegistryKey logKey = null;
RegistryKey sourceLogKey = null;
RegistryKey sourceKey = null;
try {
Debug.WriteLineIf(CompModSwitches.EventLog.TraceVerbose, "CreateEventSource: Getting local machine regkey");
if (machineName == ".")
baseKey = Registry.LocalMachine;
else
baseKey = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, machineName);
eventKey = baseKey.OpenSubKey("SYSTEM\\CurrentControlSet\\Services\\EventLog", true);
if (eventKey == null) {
if (!".".Equals(machineName))
throw new InvalidOperationException(SR.GetString(SR.RegKeyMissing, "SYSTEM\\CurrentControlSet\\Services\\EventLog", logName, source, machineName));
else
throw new InvalidOperationException(SR.GetString(SR.LocalRegKeyMissing, "SYSTEM\\CurrentControlSet\\Services\\EventLog", logName, source));
}
// The event log system only treats the first 8 characters of the log name as
// significant. If they're creating a new log, but that new log has the same
// first 8 characters as another log, the system will think they're the same.
// Throw an exception to let them know.
logKey = eventKey.OpenSubKey(logName, true);
if (logKey == null && logName.Length >= 8) {
// check for Windows embedded logs file names
string logNameFirst8 = logName.Substring(0,8);
if ( string.Compare(logNameFirst8,"AppEvent",StringComparison.OrdinalIgnoreCase) ==0 ||
string.Compare(logNameFirst8,"SecEvent",StringComparison.OrdinalIgnoreCase) ==0 ||
string.Compare(logNameFirst8,"SysEvent",StringComparison.OrdinalIgnoreCase) ==0 )
throw new ArgumentException(SR.GetString(SR.InvalidCustomerLogName, logName));
string sameLogName = FindSame8FirstCharsLog(eventKey, logName);
if ( sameLogName != null )
throw new ArgumentException(SR.GetString(SR.DuplicateLogName, logName, sameLogName));
}
bool createLogKey = (logKey == null);
if (createLogKey) {
if (SourceExists(logName, machineName, true)) {
// don't let them register a log name that already
// exists as source name, a source with the same
// name as the log will have to be created by default
if (".".Equals(machineName))
throw new ArgumentException(SR.GetString(SR.LocalLogAlreadyExistsAsSource, logName));
else
throw new ArgumentException(SR.GetString(SR.LogAlreadyExistsAsSource, logName, machineName));
}
logKey = eventKey.CreateSubKey(logName);
// NOTE: We shouldn't set "Sources" explicitly, the OS will automatically set it.
// The EventLog service doesn't use it for anything it is just an helping hand for event viewer filters.
// Writing this value explicitly might confuse the service as it might perceive it as a change and
// start initializing again
if (!SkipRegPatch)
logKey.SetValue("Sources", new string[] {logName, source}, RegistryValueKind.MultiString);
SetSpecialLogRegValues(logKey, logName);
// A source with the same name as the log has to be created
// by default. It is the behavior expected by EventLog API.
sourceLogKey = logKey.CreateSubKey(logName);
SetSpecialSourceRegValues(sourceLogKey, sourceData);
}
if (logName != source) {
if (!createLogKey) {
SetSpecialLogRegValues(logKey, logName);
if (!SkipRegPatch) {
string[] sources = logKey.GetValue("Sources") as string[];
if (sources == null)
logKey.SetValue("Sources", new string[] {logName, source}, RegistryValueKind.MultiString);
else {
// We have a ---- with OS EventLog here.
// OS might update Sources as well. We should avoid writing the
// source name if OS beats us.
if( Array.IndexOf(sources, source) == -1) {
string[] newsources = new string[sources.Length + 1];
Array.Copy(sources, newsources, sources.Length);
newsources[sources.Length] = source;
logKey.SetValue("Sources", newsources, RegistryValueKind.MultiString);
}
}
}
}
sourceKey = logKey.CreateSubKey(source);
SetSpecialSourceRegValues(sourceKey, sourceData);
}
}
finally {
if (baseKey != null)
baseKey.Close();
if (eventKey != null)
eventKey.Close();
if (logKey != null) {
logKey.Flush();
logKey.Close();
}
if (sourceLogKey != null) {
sourceLogKey.Flush();
sourceLogKey.Close();
}
if (sourceKey != null) {
sourceKey.Flush();
sourceKey.Close();
}
// Revert registry and environment permission asserts
CodeAccessPermission.RevertAssert();
}
}
finally {
if (mutex != null) {
mutex.ReleaseMutex();
mutex.Close();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment