Fix file permission and line ending issues

pull/641/head
NextTurn 2020-02-19 00:00:00 +08:00 committed by Next Turn
parent 139c98403b
commit 7554d0ecbd
9 changed files with 1610 additions and 1610 deletions

560
src/Core/WinSWCore/Download.cs Executable file → Normal file
View File

@ -1,280 +1,280 @@
using System;
using System.IO;
using System.Net;
#if !VNEXT
using System.Reflection;
#endif
using System.Text;
#if VNEXT
using System.Threading.Tasks;
#endif
using System.Xml;
using log4net;
using WinSW.Util;
namespace WinSW
{
/// <summary>
/// Specify the download activities prior to the launch.
/// This enables self-updating services.
/// </summary>
public class Download
{
public enum AuthType
{
None = 0,
Sspi,
Basic
}
private static readonly ILog Logger = LogManager.GetLogger(typeof(Download));
public readonly string From;
public readonly string To;
public readonly AuthType Auth;
public readonly string? Username;
public readonly string? Password;
public readonly bool UnsecureAuth;
public readonly bool FailOnError;
public readonly string? Proxy;
public string ShortId => $"(download from {this.From})";
static Download()
{
#if NET461
// If your app runs on .NET Framework 4.7 or later versions, but targets an earlier version
AppContext.SetSwitch("Switch.System.Net.DontEnableSystemDefaultTlsVersions", false);
#elif !VNEXT
// If your app runs on .NET Framework 4.6, but targets an earlier version
Type.GetType("System.AppContext")?.InvokeMember("SetSwitch", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, new object[] { "Switch.System.Net.DontEnableSchUseStrongCrypto", false });
const SecurityProtocolType Tls12 = (SecurityProtocolType)0x00000C00;
const SecurityProtocolType Tls11 = (SecurityProtocolType)0x00000300;
// Windows 7 and Windows Server 2008 R2
if (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor == 1)
{
try
{
ServicePointManager.SecurityProtocol |= Tls11 | Tls12;
Logger.Info("TLS 1.1/1.2 enabled");
}
catch (NotSupportedException)
{
Logger.Info("TLS 1.1/1.2 disabled");
}
}
#endif
}
// internal
public Download(
string from,
string to,
bool failOnError = false,
AuthType auth = AuthType.None,
string? username = null,
string? password = null,
bool unsecureAuth = false,
string? proxy = null)
{
this.From = from;
this.To = to;
this.FailOnError = failOnError;
this.Proxy = proxy;
this.Auth = auth;
this.Username = username;
this.Password = password;
this.UnsecureAuth = unsecureAuth;
}
/// <summary>
/// Constructs the download setting sfrom the XML entry
/// </summary>
/// <param name="n">XML element</param>
/// <exception cref="InvalidDataException">The required attribute is missing or the configuration is invalid.</exception>
internal Download(XmlElement n)
{
this.From = XmlHelper.SingleAttribute<string>(n, "from");
this.To = XmlHelper.SingleAttribute<string>(n, "to");
// All arguments below are optional
this.FailOnError = XmlHelper.SingleAttribute(n, "failOnError", false);
this.Proxy = XmlHelper.SingleAttribute<string>(n, "proxy", null);
this.Auth = XmlHelper.EnumAttribute(n, "auth", AuthType.None);
this.Username = XmlHelper.SingleAttribute<string>(n, "user", null);
this.Password = XmlHelper.SingleAttribute<string>(n, "password", null);
this.UnsecureAuth = XmlHelper.SingleAttribute(n, "unsecureAuth", false);
if (this.Auth == AuthType.Basic)
{
// Allow it only for HTTPS or for UnsecureAuth
if (!this.From.StartsWith("https:") && !this.UnsecureAuth)
{
throw new InvalidDataException("Warning: you're sending your credentials in clear text to the server " + this.ShortId +
"If you really want this you must enable 'unsecureAuth' in the configuration");
}
// Also fail if there is no user/password
if (this.Username is null)
{
throw new InvalidDataException("Basic Auth is enabled, but username is not specified " + this.ShortId);
}
if (this.Password is null)
{
throw new InvalidDataException("Basic Auth is enabled, but password is not specified " + this.ShortId);
}
}
}
// Source: http://stackoverflow.com/questions/2764577/forcing-basic-authentication-in-webrequest
private void SetBasicAuthHeader(WebRequest request, string username, string password)
{
string authInfo = username + ":" + password;
authInfo = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(authInfo));
request.Headers["Authorization"] = "Basic " + authInfo;
}
/// <summary>
/// Downloads the requested file and puts it to the specified target.
/// </summary>
/// <exception cref="WebException">
/// Download failure. FailOnError flag should be processed outside.
/// </exception>
#if VNEXT
public async Task PerformAsync()
#else
public void Perform()
#endif
{
WebRequest request = WebRequest.Create(this.From);
if (!string.IsNullOrEmpty(this.Proxy))
{
CustomProxyInformation proxyInformation = new CustomProxyInformation(this.Proxy!);
if (proxyInformation.Credentials != null)
{
request.Proxy = new WebProxy(proxyInformation.ServerAddress, false, null, proxyInformation.Credentials);
}
else
{
request.Proxy = new WebProxy(proxyInformation.ServerAddress);
}
}
switch (this.Auth)
{
case AuthType.None:
// Do nothing
break;
case AuthType.Sspi:
request.UseDefaultCredentials = true;
request.PreAuthenticate = true;
request.Credentials = CredentialCache.DefaultCredentials;
break;
case AuthType.Basic:
this.SetBasicAuthHeader(request, this.Username!, this.Password!);
break;
default:
throw new WebException("Code defect. Unsupported authentication type: " + this.Auth);
}
bool supportsIfModifiedSince = false;
if (request is HttpWebRequest httpRequest && File.Exists(this.To))
{
supportsIfModifiedSince = true;
httpRequest.IfModifiedSince = File.GetLastWriteTime(this.To);
}
DateTime lastModified = default;
string tmpFilePath = this.To + ".tmp";
try
{
#if VNEXT
using (WebResponse response = await request.GetResponseAsync())
#else
using (WebResponse response = request.GetResponse())
#endif
using (Stream responseStream = response.GetResponseStream())
using (FileStream tmpStream = new FileStream(tmpFilePath, FileMode.Create))
{
if (supportsIfModifiedSince)
{
lastModified = ((HttpWebResponse)response).LastModified;
}
#if VNEXT
await responseStream.CopyToAsync(tmpStream);
#elif NET20
CopyStream(responseStream, tmpStream);
#else
responseStream.CopyTo(tmpStream);
#endif
}
FileHelper.MoveOrReplaceFile(this.To + ".tmp", this.To);
if (supportsIfModifiedSince)
{
File.SetLastWriteTime(this.To, lastModified);
}
}
catch (WebException e)
{
if (supportsIfModifiedSince && ((HttpWebResponse)e.Response).StatusCode == HttpStatusCode.NotModified)
{
Logger.Info($"Skipped downloading unmodified resource '{this.From}'");
}
else
{
throw;
}
}
}
#if NET20
private static void CopyStream(Stream source, Stream destination)
{
byte[] buffer = new byte[8192];
int read;
while ((read = source.Read(buffer, 0, buffer.Length)) != 0)
{
destination.Write(buffer, 0, read);
}
}
#endif
}
public class CustomProxyInformation
{
public string ServerAddress { get; set; }
public NetworkCredential? Credentials { get; set; }
public CustomProxyInformation(string proxy)
{
if (proxy.Contains("@"))
{
// Extract proxy credentials
int credsFrom = proxy.IndexOf("://") + 3;
int credsTo = proxy.LastIndexOf("@");
string completeCredsStr = proxy.Substring(credsFrom, credsTo - credsFrom);
int credsSeparator = completeCredsStr.IndexOf(":");
string username = completeCredsStr.Substring(0, credsSeparator);
string password = completeCredsStr.Substring(credsSeparator + 1);
this.Credentials = new NetworkCredential(username, password);
this.ServerAddress = proxy.Replace(completeCredsStr + "@", string.Empty);
}
else
{
this.ServerAddress = proxy;
}
}
}
}
using System;
using System.IO;
using System.Net;
#if !VNEXT
using System.Reflection;
#endif
using System.Text;
#if VNEXT
using System.Threading.Tasks;
#endif
using System.Xml;
using log4net;
using WinSW.Util;
namespace WinSW
{
/// <summary>
/// Specify the download activities prior to the launch.
/// This enables self-updating services.
/// </summary>
public class Download
{
public enum AuthType
{
None = 0,
Sspi,
Basic
}
private static readonly ILog Logger = LogManager.GetLogger(typeof(Download));
public readonly string From;
public readonly string To;
public readonly AuthType Auth;
public readonly string? Username;
public readonly string? Password;
public readonly bool UnsecureAuth;
public readonly bool FailOnError;
public readonly string? Proxy;
public string ShortId => $"(download from {this.From})";
static Download()
{
#if NET461
// If your app runs on .NET Framework 4.7 or later versions, but targets an earlier version
AppContext.SetSwitch("Switch.System.Net.DontEnableSystemDefaultTlsVersions", false);
#elif !VNEXT
// If your app runs on .NET Framework 4.6, but targets an earlier version
Type.GetType("System.AppContext")?.InvokeMember("SetSwitch", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, new object[] { "Switch.System.Net.DontEnableSchUseStrongCrypto", false });
const SecurityProtocolType Tls12 = (SecurityProtocolType)0x00000C00;
const SecurityProtocolType Tls11 = (SecurityProtocolType)0x00000300;
// Windows 7 and Windows Server 2008 R2
if (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor == 1)
{
try
{
ServicePointManager.SecurityProtocol |= Tls11 | Tls12;
Logger.Info("TLS 1.1/1.2 enabled");
}
catch (NotSupportedException)
{
Logger.Info("TLS 1.1/1.2 disabled");
}
}
#endif
}
// internal
public Download(
string from,
string to,
bool failOnError = false,
AuthType auth = AuthType.None,
string? username = null,
string? password = null,
bool unsecureAuth = false,
string? proxy = null)
{
this.From = from;
this.To = to;
this.FailOnError = failOnError;
this.Proxy = proxy;
this.Auth = auth;
this.Username = username;
this.Password = password;
this.UnsecureAuth = unsecureAuth;
}
/// <summary>
/// Constructs the download setting sfrom the XML entry
/// </summary>
/// <param name="n">XML element</param>
/// <exception cref="InvalidDataException">The required attribute is missing or the configuration is invalid.</exception>
internal Download(XmlElement n)
{
this.From = XmlHelper.SingleAttribute<string>(n, "from");
this.To = XmlHelper.SingleAttribute<string>(n, "to");
// All arguments below are optional
this.FailOnError = XmlHelper.SingleAttribute(n, "failOnError", false);
this.Proxy = XmlHelper.SingleAttribute<string>(n, "proxy", null);
this.Auth = XmlHelper.EnumAttribute(n, "auth", AuthType.None);
this.Username = XmlHelper.SingleAttribute<string>(n, "user", null);
this.Password = XmlHelper.SingleAttribute<string>(n, "password", null);
this.UnsecureAuth = XmlHelper.SingleAttribute(n, "unsecureAuth", false);
if (this.Auth == AuthType.Basic)
{
// Allow it only for HTTPS or for UnsecureAuth
if (!this.From.StartsWith("https:") && !this.UnsecureAuth)
{
throw new InvalidDataException("Warning: you're sending your credentials in clear text to the server " + this.ShortId +
"If you really want this you must enable 'unsecureAuth' in the configuration");
}
// Also fail if there is no user/password
if (this.Username is null)
{
throw new InvalidDataException("Basic Auth is enabled, but username is not specified " + this.ShortId);
}
if (this.Password is null)
{
throw new InvalidDataException("Basic Auth is enabled, but password is not specified " + this.ShortId);
}
}
}
// Source: http://stackoverflow.com/questions/2764577/forcing-basic-authentication-in-webrequest
private void SetBasicAuthHeader(WebRequest request, string username, string password)
{
string authInfo = username + ":" + password;
authInfo = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(authInfo));
request.Headers["Authorization"] = "Basic " + authInfo;
}
/// <summary>
/// Downloads the requested file and puts it to the specified target.
/// </summary>
/// <exception cref="WebException">
/// Download failure. FailOnError flag should be processed outside.
/// </exception>
#if VNEXT
public async Task PerformAsync()
#else
public void Perform()
#endif
{
WebRequest request = WebRequest.Create(this.From);
if (!string.IsNullOrEmpty(this.Proxy))
{
CustomProxyInformation proxyInformation = new CustomProxyInformation(this.Proxy!);
if (proxyInformation.Credentials != null)
{
request.Proxy = new WebProxy(proxyInformation.ServerAddress, false, null, proxyInformation.Credentials);
}
else
{
request.Proxy = new WebProxy(proxyInformation.ServerAddress);
}
}
switch (this.Auth)
{
case AuthType.None:
// Do nothing
break;
case AuthType.Sspi:
request.UseDefaultCredentials = true;
request.PreAuthenticate = true;
request.Credentials = CredentialCache.DefaultCredentials;
break;
case AuthType.Basic:
this.SetBasicAuthHeader(request, this.Username!, this.Password!);
break;
default:
throw new WebException("Code defect. Unsupported authentication type: " + this.Auth);
}
bool supportsIfModifiedSince = false;
if (request is HttpWebRequest httpRequest && File.Exists(this.To))
{
supportsIfModifiedSince = true;
httpRequest.IfModifiedSince = File.GetLastWriteTime(this.To);
}
DateTime lastModified = default;
string tmpFilePath = this.To + ".tmp";
try
{
#if VNEXT
using (WebResponse response = await request.GetResponseAsync())
#else
using (WebResponse response = request.GetResponse())
#endif
using (Stream responseStream = response.GetResponseStream())
using (FileStream tmpStream = new FileStream(tmpFilePath, FileMode.Create))
{
if (supportsIfModifiedSince)
{
lastModified = ((HttpWebResponse)response).LastModified;
}
#if VNEXT
await responseStream.CopyToAsync(tmpStream);
#elif NET20
CopyStream(responseStream, tmpStream);
#else
responseStream.CopyTo(tmpStream);
#endif
}
FileHelper.MoveOrReplaceFile(this.To + ".tmp", this.To);
if (supportsIfModifiedSince)
{
File.SetLastWriteTime(this.To, lastModified);
}
}
catch (WebException e)
{
if (supportsIfModifiedSince && ((HttpWebResponse)e.Response).StatusCode == HttpStatusCode.NotModified)
{
Logger.Info($"Skipped downloading unmodified resource '{this.From}'");
}
else
{
throw;
}
}
}
#if NET20
private static void CopyStream(Stream source, Stream destination)
{
byte[] buffer = new byte[8192];
int read;
while ((read = source.Read(buffer, 0, buffer.Length)) != 0)
{
destination.Write(buffer, 0, read);
}
}
#endif
}
public class CustomProxyInformation
{
public string ServerAddress { get; set; }
public NetworkCredential? Credentials { get; set; }
public CustomProxyInformation(string proxy)
{
if (proxy.Contains("@"))
{
// Extract proxy credentials
int credsFrom = proxy.IndexOf("://") + 3;
int credsTo = proxy.LastIndexOf("@");
string completeCredsStr = proxy.Substring(credsFrom, credsTo - credsFrom);
int credsSeparator = completeCredsStr.IndexOf(":");
string username = completeCredsStr.Substring(0, credsSeparator);
string password = completeCredsStr.Substring(credsSeparator + 1);
this.Credentials = new NetworkCredential(username, password);
this.ServerAddress = proxy.Replace(completeCredsStr + "@", string.Empty);
}
else
{
this.ServerAddress = proxy;
}
}
}
}

View File

@ -1,205 +1,205 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
namespace DynamicProxy
{
/// <summary>
/// Interface that a user defined proxy handler needs to implement. This interface
/// defines one method that gets invoked by the generated proxy.
/// </summary>
public interface IProxyInvocationHandler
{
/// <param name="proxy">The instance of the proxy</param>
/// <param name="method">The method info that can be used to invoke the actual method on the object implementation</param>
/// <param name="parameters">Parameters to pass to the method</param>
/// <returns>Object</returns>
object? Invoke(object proxy, MethodInfo method, object[] parameters);
}
/// <summary>
/// </summary>
public static class ProxyFactory
{
private const string ProxySuffix = "Proxy";
private const string AssemblyName = "ProxyAssembly";
private const string ModuleName = "ProxyModule";
private const string HandlerName = "handler";
private static readonly Dictionary<string, Type> TypeCache = new Dictionary<string, Type>();
private static readonly AssemblyBuilder AssemblyBuilder =
#if VNEXT
AssemblyBuilder.DefineDynamicAssembly(
#else
AppDomain.CurrentDomain.DefineDynamicAssembly(
#endif
new AssemblyName(AssemblyName), AssemblyBuilderAccess.Run);
private static readonly ModuleBuilder ModuleBuilder = AssemblyBuilder.DefineDynamicModule(ModuleName);
public static object Create(IProxyInvocationHandler handler, Type objType, bool isObjInterface = false)
{
string typeName = objType.FullName + ProxySuffix;
Type? type = null;
lock (TypeCache)
{
if (!TypeCache.TryGetValue(typeName, out type))
{
type = CreateType(typeName, isObjInterface ? new Type[] { objType } : objType.GetInterfaces());
TypeCache.Add(typeName, type);
}
}
return Activator.CreateInstance(type, new object[] { handler })!;
}
private static Type CreateType(string dynamicTypeName, Type[] interfaces)
{
Type objType = typeof(object);
Type handlerType = typeof(IProxyInvocationHandler);
TypeAttributes typeAttributes = TypeAttributes.Public | TypeAttributes.Sealed;
// Gather up the proxy information and create a new type builder. One that
// inherits from Object and implements the interface passed in
TypeBuilder typeBuilder = ModuleBuilder.DefineType(
dynamicTypeName, typeAttributes, objType, interfaces);
// Define a member variable to hold the delegate
FieldBuilder handlerField = typeBuilder.DefineField(
HandlerName, handlerType, FieldAttributes.Private | FieldAttributes.InitOnly);
// build a constructor that takes the delegate object as the only argument
ConstructorInfo baseConstructor = objType.GetConstructor(Type.EmptyTypes)!;
ConstructorBuilder delegateConstructor = typeBuilder.DefineConstructor(
MethodAttributes.Public, CallingConventions.Standard, new Type[] { handlerType });
ILGenerator constructorIL = delegateConstructor.GetILGenerator();
// Load "this"
constructorIL.Emit(OpCodes.Ldarg_0);
// Load first constructor parameter
constructorIL.Emit(OpCodes.Ldarg_1);
// Set the first parameter into the handler field
constructorIL.Emit(OpCodes.Stfld, handlerField);
// Load "this"
constructorIL.Emit(OpCodes.Ldarg_0);
// Call the super constructor
constructorIL.Emit(OpCodes.Call, baseConstructor);
// Constructor return
constructorIL.Emit(OpCodes.Ret);
// for every method that the interfaces define, build a corresponding
// method in the dynamic type that calls the handlers invoke method.
foreach (Type interfaceType in interfaces)
{
GenerateMethod(interfaceType, handlerField, typeBuilder);
}
return typeBuilder.CreateType()!;
}
/// <summary>
/// <see cref="IProxyInvocationHandler.Invoke(object, MethodInfo, object[])"/>.
/// </summary>
private static readonly MethodInfo InvokeMethod = typeof(IProxyInvocationHandler).GetMethod(nameof(IProxyInvocationHandler.Invoke))!;
/// <summary>
/// <see cref="MethodBase.GetMethodFromHandle(RuntimeMethodHandle)"/>.
/// </summary>
private static readonly MethodInfo GetMethodFromHandleMethod = typeof(MethodBase).GetMethod(nameof(MethodBase.GetMethodFromHandle), new[] { typeof(RuntimeMethodHandle) })!;
private static void GenerateMethod(Type interfaceType, FieldBuilder handlerField, TypeBuilder typeBuilder)
{
MethodInfo[] interfaceMethods = interfaceType.GetMethods();
for (int i = 0; i < interfaceMethods.Length; i++)
{
MethodInfo methodInfo = interfaceMethods[i];
// Get the method parameters since we need to create an array
// of parameter types
ParameterInfo[] methodParams = methodInfo.GetParameters();
int numOfParams = methodParams.Length;
Type[] methodParameters = new Type[numOfParams];
// convert the ParameterInfo objects into Type
for (int j = 0; j < numOfParams; j++)
{
methodParameters[j] = methodParams[j].ParameterType;
}
// create a new builder for the method in the interface
MethodBuilder methodBuilder = typeBuilder.DefineMethod(
methodInfo.Name,
/*MethodAttributes.Public | MethodAttributes.Virtual | */ methodInfo.Attributes & ~MethodAttributes.Abstract,
CallingConventions.Standard,
methodInfo.ReturnType,
methodParameters);
ILGenerator methodIL = methodBuilder.GetILGenerator();
// invoke target: IProxyInvocationHandler
methodIL.Emit(OpCodes.Ldarg_0);
methodIL.Emit(OpCodes.Ldfld, handlerField);
// 1st parameter: object proxy
methodIL.Emit(OpCodes.Ldarg_0);
// 2nd parameter: MethodInfo method
methodIL.Emit(OpCodes.Ldtoken, methodInfo);
methodIL.Emit(OpCodes.Call, GetMethodFromHandleMethod);
methodIL.Emit(OpCodes.Castclass, typeof(MethodInfo));
// 3rd parameter: object[] parameters
methodIL.Emit(OpCodes.Ldc_I4, numOfParams);
methodIL.Emit(OpCodes.Newarr, typeof(object));
// if we have any parameters, then iterate through and set the values
// of each element to the corresponding arguments
for (int j = 0; j < numOfParams; j++)
{
methodIL.Emit(OpCodes.Dup); // copy the array
methodIL.Emit(OpCodes.Ldc_I4, j);
methodIL.Emit(OpCodes.Ldarg, j + 1); // +1 for "this"
if (methodParameters[j].IsValueType)
{
methodIL.Emit(OpCodes.Box, methodParameters[j]);
}
methodIL.Emit(OpCodes.Stelem_Ref);
}
// call the Invoke method
methodIL.Emit(OpCodes.Callvirt, InvokeMethod);
if (methodInfo.ReturnType != typeof(void))
{
methodIL.Emit(OpCodes.Unbox_Any, methodInfo.ReturnType);
}
else
{
// pop the return value that Invoke returned from the stack since
// the method's return type is void.
methodIL.Emit(OpCodes.Pop);
}
// Return
methodIL.Emit(OpCodes.Ret);
}
// Iterate through the parent interfaces and recursively call this method
foreach (Type parentType in interfaceType.GetInterfaces())
{
GenerateMethod(parentType, handlerField, typeBuilder);
}
}
}
}
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
namespace DynamicProxy
{
/// <summary>
/// Interface that a user defined proxy handler needs to implement. This interface
/// defines one method that gets invoked by the generated proxy.
/// </summary>
public interface IProxyInvocationHandler
{
/// <param name="proxy">The instance of the proxy</param>
/// <param name="method">The method info that can be used to invoke the actual method on the object implementation</param>
/// <param name="parameters">Parameters to pass to the method</param>
/// <returns>Object</returns>
object? Invoke(object proxy, MethodInfo method, object[] parameters);
}
/// <summary>
/// </summary>
public static class ProxyFactory
{
private const string ProxySuffix = "Proxy";
private const string AssemblyName = "ProxyAssembly";
private const string ModuleName = "ProxyModule";
private const string HandlerName = "handler";
private static readonly Dictionary<string, Type> TypeCache = new Dictionary<string, Type>();
private static readonly AssemblyBuilder AssemblyBuilder =
#if VNEXT
AssemblyBuilder.DefineDynamicAssembly(
#else
AppDomain.CurrentDomain.DefineDynamicAssembly(
#endif
new AssemblyName(AssemblyName), AssemblyBuilderAccess.Run);
private static readonly ModuleBuilder ModuleBuilder = AssemblyBuilder.DefineDynamicModule(ModuleName);
public static object Create(IProxyInvocationHandler handler, Type objType, bool isObjInterface = false)
{
string typeName = objType.FullName + ProxySuffix;
Type? type = null;
lock (TypeCache)
{
if (!TypeCache.TryGetValue(typeName, out type))
{
type = CreateType(typeName, isObjInterface ? new Type[] { objType } : objType.GetInterfaces());
TypeCache.Add(typeName, type);
}
}
return Activator.CreateInstance(type, new object[] { handler })!;
}
private static Type CreateType(string dynamicTypeName, Type[] interfaces)
{
Type objType = typeof(object);
Type handlerType = typeof(IProxyInvocationHandler);
TypeAttributes typeAttributes = TypeAttributes.Public | TypeAttributes.Sealed;
// Gather up the proxy information and create a new type builder. One that
// inherits from Object and implements the interface passed in
TypeBuilder typeBuilder = ModuleBuilder.DefineType(
dynamicTypeName, typeAttributes, objType, interfaces);
// Define a member variable to hold the delegate
FieldBuilder handlerField = typeBuilder.DefineField(
HandlerName, handlerType, FieldAttributes.Private | FieldAttributes.InitOnly);
// build a constructor that takes the delegate object as the only argument
ConstructorInfo baseConstructor = objType.GetConstructor(Type.EmptyTypes)!;
ConstructorBuilder delegateConstructor = typeBuilder.DefineConstructor(
MethodAttributes.Public, CallingConventions.Standard, new Type[] { handlerType });
ILGenerator constructorIL = delegateConstructor.GetILGenerator();
// Load "this"
constructorIL.Emit(OpCodes.Ldarg_0);
// Load first constructor parameter
constructorIL.Emit(OpCodes.Ldarg_1);
// Set the first parameter into the handler field
constructorIL.Emit(OpCodes.Stfld, handlerField);
// Load "this"
constructorIL.Emit(OpCodes.Ldarg_0);
// Call the super constructor
constructorIL.Emit(OpCodes.Call, baseConstructor);
// Constructor return
constructorIL.Emit(OpCodes.Ret);
// for every method that the interfaces define, build a corresponding
// method in the dynamic type that calls the handlers invoke method.
foreach (Type interfaceType in interfaces)
{
GenerateMethod(interfaceType, handlerField, typeBuilder);
}
return typeBuilder.CreateType()!;
}
/// <summary>
/// <see cref="IProxyInvocationHandler.Invoke(object, MethodInfo, object[])"/>.
/// </summary>
private static readonly MethodInfo InvokeMethod = typeof(IProxyInvocationHandler).GetMethod(nameof(IProxyInvocationHandler.Invoke))!;
/// <summary>
/// <see cref="MethodBase.GetMethodFromHandle(RuntimeMethodHandle)"/>.
/// </summary>
private static readonly MethodInfo GetMethodFromHandleMethod = typeof(MethodBase).GetMethod(nameof(MethodBase.GetMethodFromHandle), new[] { typeof(RuntimeMethodHandle) })!;
private static void GenerateMethod(Type interfaceType, FieldBuilder handlerField, TypeBuilder typeBuilder)
{
MethodInfo[] interfaceMethods = interfaceType.GetMethods();
for (int i = 0; i < interfaceMethods.Length; i++)
{
MethodInfo methodInfo = interfaceMethods[i];
// Get the method parameters since we need to create an array
// of parameter types
ParameterInfo[] methodParams = methodInfo.GetParameters();
int numOfParams = methodParams.Length;
Type[] methodParameters = new Type[numOfParams];
// convert the ParameterInfo objects into Type
for (int j = 0; j < numOfParams; j++)
{
methodParameters[j] = methodParams[j].ParameterType;
}
// create a new builder for the method in the interface
MethodBuilder methodBuilder = typeBuilder.DefineMethod(
methodInfo.Name,
/*MethodAttributes.Public | MethodAttributes.Virtual | */ methodInfo.Attributes & ~MethodAttributes.Abstract,
CallingConventions.Standard,
methodInfo.ReturnType,
methodParameters);
ILGenerator methodIL = methodBuilder.GetILGenerator();
// invoke target: IProxyInvocationHandler
methodIL.Emit(OpCodes.Ldarg_0);
methodIL.Emit(OpCodes.Ldfld, handlerField);
// 1st parameter: object proxy
methodIL.Emit(OpCodes.Ldarg_0);
// 2nd parameter: MethodInfo method
methodIL.Emit(OpCodes.Ldtoken, methodInfo);
methodIL.Emit(OpCodes.Call, GetMethodFromHandleMethod);
methodIL.Emit(OpCodes.Castclass, typeof(MethodInfo));
// 3rd parameter: object[] parameters
methodIL.Emit(OpCodes.Ldc_I4, numOfParams);
methodIL.Emit(OpCodes.Newarr, typeof(object));
// if we have any parameters, then iterate through and set the values
// of each element to the corresponding arguments
for (int j = 0; j < numOfParams; j++)
{
methodIL.Emit(OpCodes.Dup); // copy the array
methodIL.Emit(OpCodes.Ldc_I4, j);
methodIL.Emit(OpCodes.Ldarg, j + 1); // +1 for "this"
if (methodParameters[j].IsValueType)
{
methodIL.Emit(OpCodes.Box, methodParameters[j]);
}
methodIL.Emit(OpCodes.Stelem_Ref);
}
// call the Invoke method
methodIL.Emit(OpCodes.Callvirt, InvokeMethod);
if (methodInfo.ReturnType != typeof(void))
{
methodIL.Emit(OpCodes.Unbox_Any, methodInfo.ReturnType);
}
else
{
// pop the return value that Invoke returned from the stack since
// the method's return type is void.
methodIL.Emit(OpCodes.Pop);
}
// Return
methodIL.Emit(OpCodes.Ret);
}
// Iterate through the parent interfaces and recursively call this method
foreach (Type parentType in interfaceType.GetInterfaces())
{
GenerateMethod(parentType, handlerField, typeBuilder);
}
}
}
}

File diff suppressed because it is too large Load Diff

22
src/Core/WinSWCore/Native/Kernel32.cs Executable file → Normal file
View File

@ -1,11 +1,11 @@
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
namespace WinSW.Native
{
internal static class Kernel32
{
[DllImport(Libraries.Kernel32)]
internal static extern bool SetStdHandle(int stdHandle, SafeFileHandle handle);
}
}
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
namespace WinSW.Native
{
internal static class Kernel32
{
[DllImport(Libraries.Kernel32)]
internal static extern bool SetStdHandle(int stdHandle, SafeFileHandle handle);
}
}

View File

@ -1,108 +1,108 @@
using System;
namespace WinSW
{
// This is largely borrowed from the logback Rolling Calendar.
public class PeriodicRollingCalendar
{
private readonly string format;
private readonly long period;
private DateTime currentRoll;
private DateTime nextRoll;
public PeriodicRollingCalendar(string format, long period)
{
this.format = format;
this.period = period;
this.currentRoll = DateTime.Now;
}
public void Init()
{
this.PeriodicityType = this.DeterminePeriodicityType();
this.nextRoll = this.NextTriggeringTime(this.currentRoll, this.period);
}
public enum Periodicity
{
ERRONEOUS,
TOP_OF_MILLISECOND,
TOP_OF_SECOND,
TOP_OF_MINUTE,
TOP_OF_HOUR,
TOP_OF_DAY
}
private static readonly Periodicity[] ValidOrderedList =
{
Periodicity.TOP_OF_MILLISECOND, Periodicity.TOP_OF_SECOND, Periodicity.TOP_OF_MINUTE, Periodicity.TOP_OF_HOUR, Periodicity.TOP_OF_DAY
};
private Periodicity DeterminePeriodicityType()
{
PeriodicRollingCalendar periodicRollingCalendar = new PeriodicRollingCalendar(this.format, this.period);
DateTime epoch = new DateTime(1970, 1, 1);
foreach (Periodicity i in ValidOrderedList)
{
string r0 = epoch.ToString(this.format);
periodicRollingCalendar.PeriodicityType = i;
DateTime next = periodicRollingCalendar.NextTriggeringTime(epoch, 1);
string r1 = next.ToString(this.format);
if (r0 != r1)
{
return i;
}
}
return Periodicity.ERRONEOUS;
}
private DateTime NextTriggeringTime(DateTime input, long increment) => this.PeriodicityType switch
{
Periodicity.TOP_OF_MILLISECOND =>
new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, input.Second, input.Millisecond)
.AddMilliseconds(increment),
Periodicity.TOP_OF_SECOND =>
new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, input.Second)
.AddSeconds(increment),
Periodicity.TOP_OF_MINUTE =>
new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, 0)
.AddMinutes(increment),
Periodicity.TOP_OF_HOUR =>
new DateTime(input.Year, input.Month, input.Day, input.Hour, 0, 0)
.AddHours(increment),
Periodicity.TOP_OF_DAY =>
new DateTime(input.Year, input.Month, input.Day)
.AddDays(increment),
_ => throw new Exception("invalid periodicity type: " + this.PeriodicityType),
};
public Periodicity PeriodicityType { get; set; }
public bool ShouldRoll
{
get
{
DateTime now = DateTime.Now;
if (now > this.nextRoll)
{
this.currentRoll = now;
this.nextRoll = this.NextTriggeringTime(now, this.period);
return true;
}
return false;
}
}
public string Format => this.currentRoll.ToString(this.format);
}
}
using System;
namespace WinSW
{
// This is largely borrowed from the logback Rolling Calendar.
public class PeriodicRollingCalendar
{
private readonly string format;
private readonly long period;
private DateTime currentRoll;
private DateTime nextRoll;
public PeriodicRollingCalendar(string format, long period)
{
this.format = format;
this.period = period;
this.currentRoll = DateTime.Now;
}
public void Init()
{
this.PeriodicityType = this.DeterminePeriodicityType();
this.nextRoll = this.NextTriggeringTime(this.currentRoll, this.period);
}
public enum Periodicity
{
ERRONEOUS,
TOP_OF_MILLISECOND,
TOP_OF_SECOND,
TOP_OF_MINUTE,
TOP_OF_HOUR,
TOP_OF_DAY
}
private static readonly Periodicity[] ValidOrderedList =
{
Periodicity.TOP_OF_MILLISECOND, Periodicity.TOP_OF_SECOND, Periodicity.TOP_OF_MINUTE, Periodicity.TOP_OF_HOUR, Periodicity.TOP_OF_DAY
};
private Periodicity DeterminePeriodicityType()
{
PeriodicRollingCalendar periodicRollingCalendar = new PeriodicRollingCalendar(this.format, this.period);
DateTime epoch = new DateTime(1970, 1, 1);
foreach (Periodicity i in ValidOrderedList)
{
string r0 = epoch.ToString(this.format);
periodicRollingCalendar.PeriodicityType = i;
DateTime next = periodicRollingCalendar.NextTriggeringTime(epoch, 1);
string r1 = next.ToString(this.format);
if (r0 != r1)
{
return i;
}
}
return Periodicity.ERRONEOUS;
}
private DateTime NextTriggeringTime(DateTime input, long increment) => this.PeriodicityType switch
{
Periodicity.TOP_OF_MILLISECOND =>
new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, input.Second, input.Millisecond)
.AddMilliseconds(increment),
Periodicity.TOP_OF_SECOND =>
new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, input.Second)
.AddSeconds(increment),
Periodicity.TOP_OF_MINUTE =>
new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, 0)
.AddMinutes(increment),
Periodicity.TOP_OF_HOUR =>
new DateTime(input.Year, input.Month, input.Day, input.Hour, 0, 0)
.AddHours(increment),
Periodicity.TOP_OF_DAY =>
new DateTime(input.Year, input.Month, input.Day)
.AddDays(increment),
_ => throw new Exception("invalid periodicity type: " + this.PeriodicityType),
};
public Periodicity PeriodicityType { get; set; }
public bool ShouldRoll
{
get
{
DateTime now = DateTime.Now;
if (now > this.nextRoll)
{
this.currentRoll = now;
this.nextRoll = this.NextTriggeringTime(now, this.period);
return true;
}
return false;
}
}
public string Format => this.currentRoll.ToString(this.format);
}
}

0
src/Core/WinSWCore/ServiceDescriptor.cs Executable file → Normal file
View File

454
src/Core/WinSWCore/Wmi.cs Executable file → Normal file
View File

@ -1,227 +1,227 @@
using System;
using System.Management;
using System.Reflection;
using System.Text;
using DynamicProxy;
namespace WMI
{
// https://docs.microsoft.com/windows/win32/cimwin32prov/create-method-in-class-win32-service
public enum ReturnValue : uint
{
Success = 0,
NotSupported = 1,
AccessDenied = 2,
DependentServicesRunning = 3,
InvalidServiceControl = 4,
ServiceCannotAcceptControl = 5,
ServiceNotActive = 6,
ServiceRequestTimeout = 7,
UnknownFailure = 8,
PathNotFound = 9,
ServiceAlreadyRunning = 10,
ServiceDatabaseLocked = 11,
ServiceDependencyDeleted = 12,
ServiceDependencyFailure = 13,
ServiceDisabled = 14,
ServiceLogonFailure = 15,
ServiceMarkedForDeletion = 16,
ServiceNoThread = 17,
StatusCircularDependency = 18,
StatusDuplicateName = 19,
StatusInvalidName = 20,
StatusInvalidParameter = 21,
StatusInvalidServiceAccount = 22,
StatusServiceExists = 23,
ServiceAlreadyPaused = 24,
NoSuchService = 200
}
/// <summary>
/// Signals a problem in WMI related operations
/// </summary>
public class WmiException : Exception
{
public readonly ReturnValue ErrorCode;
public WmiException(string message, ReturnValue code)
: base(message)
{
this.ErrorCode = code;
}
public WmiException(ReturnValue code)
: this(code.ToString(), code)
{
}
}
/// <summary>
/// Associated a WMI class name to the proxy interface (which should extend from IWmiCollection)
/// </summary>
public class WmiClassName : Attribute
{
public readonly string Name;
public WmiClassName(string name) => this.Name = name;
}
/// <summary>
/// Marker interface to denote a collection in WMI.
/// </summary>
public interface IWmiCollection
{
}
/// <summary>
/// Marker interface to denote an individual managed object
/// </summary>
public interface IWmiObject
{
}
public sealed class WmiRoot
{
private readonly ManagementScope wmiScope;
public WmiRoot()
{
ConnectionOptions options = new ConnectionOptions
{
EnablePrivileges = true,
Impersonation = ImpersonationLevel.Impersonate,
Authentication = AuthenticationLevel.PacketPrivacy,
};
this.wmiScope = new ManagementScope(@"\\.\root\cimv2", options);
this.wmiScope.Connect();
}
private static string Capitalize(string s)
{
return char.ToUpper(s[0]) + s.Substring(1);
}
private abstract class BaseHandler : IProxyInvocationHandler
{
public abstract object? Invoke(object proxy, MethodInfo method, object[] arguments);
protected void CheckError(ManagementBaseObject result)
{
uint code = (uint)result["returnValue"];
if (code != 0)
{
throw new WmiException((ReturnValue)code);
}
}
protected ManagementBaseObject GetMethodParameters(ManagementObject wmiObject, string methodName, ParameterInfo[] methodParameters, object[] arguments)
{
ManagementBaseObject wmiParameters = wmiObject.GetMethodParameters(methodName);
for (int i = 0; i < arguments.Length; i++)
{
string capitalizedName = Capitalize(methodParameters[i].Name!);
wmiParameters[capitalizedName] = arguments[i];
}
return wmiParameters;
}
}
private class InstanceHandler : BaseHandler, IWmiObject
{
private readonly ManagementObject wmiObject;
public InstanceHandler(ManagementObject wmiObject) => this.wmiObject = wmiObject;
public override object? Invoke(object proxy, MethodInfo method, object[] arguments)
{
if (method.DeclaringType == typeof(IWmiObject))
{
return method.Invoke(this, arguments);
}
// TODO: proper property support
if (method.Name.StartsWith("set_"))
{
this.wmiObject[method.Name.Substring(4)] = arguments[0];
return null;
}
if (method.Name.StartsWith("get_"))
{
return this.wmiObject[method.Name.Substring(4)];
}
string methodName = method.Name;
using ManagementBaseObject? wmiParameters = arguments.Length == 0 ? null :
this.GetMethodParameters(this.wmiObject, methodName, method.GetParameters(), arguments);
using ManagementBaseObject result = this.wmiObject.InvokeMethod(methodName, wmiParameters, null);
this.CheckError(result);
return null;
}
}
private class ClassHandler : BaseHandler
{
private readonly ManagementClass wmiClass;
private readonly string className;
public ClassHandler(ManagementScope wmiScope, string className)
{
this.wmiClass = new ManagementClass(wmiScope, new ManagementPath(className), null);
this.className = className;
}
public override object? Invoke(object proxy, MethodInfo method, object[] arguments)
{
ParameterInfo[] methodParameters = method.GetParameters();
if (method.Name == nameof(IWin32Services.Select))
{
// select method to find instances
StringBuilder query = new StringBuilder("SELECT * FROM ").Append(this.className).Append(" WHERE ");
for (int i = 0; i < arguments.Length; i++)
{
if (i != 0)
{
query.Append(" AND ");
}
query.Append(' ').Append(Capitalize(methodParameters[i].Name!)).Append(" = '").Append(arguments[i]).Append('\'');
}
using ManagementObjectSearcher searcher = new ManagementObjectSearcher(this.wmiClass.Scope, new ObjectQuery(query.ToString()));
using ManagementObjectCollection results = searcher.Get();
// TODO: support collections
foreach (ManagementObject wmiObject in results)
{
return ProxyFactory.Create(new InstanceHandler(wmiObject), method.ReturnType, true);
}
return null;
}
string methodName = method.Name;
using ManagementBaseObject? wmiParameters = arguments.Length == 0 ? null :
this.GetMethodParameters(this.wmiClass, methodName, methodParameters, arguments);
using ManagementBaseObject result = this.wmiClass.InvokeMethod(methodName, wmiParameters, null);
this.CheckError(result);
return null;
}
}
/// <summary>
/// Obtains an object that corresponds to a table in WMI, which is a collection of a managed object.
/// </summary>
public T GetCollection<T>()
where T : IWmiCollection
{
WmiClassName className = (WmiClassName)typeof(T).GetCustomAttributes(typeof(WmiClassName), false)[0];
return (T)ProxyFactory.Create(new ClassHandler(this.wmiScope, className.Name), typeof(T), true);
}
}
}
using System;
using System.Management;
using System.Reflection;
using System.Text;
using DynamicProxy;
namespace WMI
{
// https://docs.microsoft.com/windows/win32/cimwin32prov/create-method-in-class-win32-service
public enum ReturnValue : uint
{
Success = 0,
NotSupported = 1,
AccessDenied = 2,
DependentServicesRunning = 3,
InvalidServiceControl = 4,
ServiceCannotAcceptControl = 5,
ServiceNotActive = 6,
ServiceRequestTimeout = 7,
UnknownFailure = 8,
PathNotFound = 9,
ServiceAlreadyRunning = 10,
ServiceDatabaseLocked = 11,
ServiceDependencyDeleted = 12,
ServiceDependencyFailure = 13,
ServiceDisabled = 14,
ServiceLogonFailure = 15,
ServiceMarkedForDeletion = 16,
ServiceNoThread = 17,
StatusCircularDependency = 18,
StatusDuplicateName = 19,
StatusInvalidName = 20,
StatusInvalidParameter = 21,
StatusInvalidServiceAccount = 22,
StatusServiceExists = 23,
ServiceAlreadyPaused = 24,
NoSuchService = 200
}
/// <summary>
/// Signals a problem in WMI related operations
/// </summary>
public class WmiException : Exception
{
public readonly ReturnValue ErrorCode;
public WmiException(string message, ReturnValue code)
: base(message)
{
this.ErrorCode = code;
}
public WmiException(ReturnValue code)
: this(code.ToString(), code)
{
}
}
/// <summary>
/// Associated a WMI class name to the proxy interface (which should extend from IWmiCollection)
/// </summary>
public class WmiClassName : Attribute
{
public readonly string Name;
public WmiClassName(string name) => this.Name = name;
}
/// <summary>
/// Marker interface to denote a collection in WMI.
/// </summary>
public interface IWmiCollection
{
}
/// <summary>
/// Marker interface to denote an individual managed object
/// </summary>
public interface IWmiObject
{
}
public sealed class WmiRoot
{
private readonly ManagementScope wmiScope;
public WmiRoot()
{
ConnectionOptions options = new ConnectionOptions
{
EnablePrivileges = true,
Impersonation = ImpersonationLevel.Impersonate,
Authentication = AuthenticationLevel.PacketPrivacy,
};
this.wmiScope = new ManagementScope(@"\\.\root\cimv2", options);
this.wmiScope.Connect();
}
private static string Capitalize(string s)
{
return char.ToUpper(s[0]) + s.Substring(1);
}
private abstract class BaseHandler : IProxyInvocationHandler
{
public abstract object? Invoke(object proxy, MethodInfo method, object[] arguments);
protected void CheckError(ManagementBaseObject result)
{
uint code = (uint)result["returnValue"];
if (code != 0)
{
throw new WmiException((ReturnValue)code);
}
}
protected ManagementBaseObject GetMethodParameters(ManagementObject wmiObject, string methodName, ParameterInfo[] methodParameters, object[] arguments)
{
ManagementBaseObject wmiParameters = wmiObject.GetMethodParameters(methodName);
for (int i = 0; i < arguments.Length; i++)
{
string capitalizedName = Capitalize(methodParameters[i].Name!);
wmiParameters[capitalizedName] = arguments[i];
}
return wmiParameters;
}
}
private class InstanceHandler : BaseHandler, IWmiObject
{
private readonly ManagementObject wmiObject;
public InstanceHandler(ManagementObject wmiObject) => this.wmiObject = wmiObject;
public override object? Invoke(object proxy, MethodInfo method, object[] arguments)
{
if (method.DeclaringType == typeof(IWmiObject))
{
return method.Invoke(this, arguments);
}
// TODO: proper property support
if (method.Name.StartsWith("set_"))
{
this.wmiObject[method.Name.Substring(4)] = arguments[0];
return null;
}
if (method.Name.StartsWith("get_"))
{
return this.wmiObject[method.Name.Substring(4)];
}
string methodName = method.Name;
using ManagementBaseObject? wmiParameters = arguments.Length == 0 ? null :
this.GetMethodParameters(this.wmiObject, methodName, method.GetParameters(), arguments);
using ManagementBaseObject result = this.wmiObject.InvokeMethod(methodName, wmiParameters, null);
this.CheckError(result);
return null;
}
}
private class ClassHandler : BaseHandler
{
private readonly ManagementClass wmiClass;
private readonly string className;
public ClassHandler(ManagementScope wmiScope, string className)
{
this.wmiClass = new ManagementClass(wmiScope, new ManagementPath(className), null);
this.className = className;
}
public override object? Invoke(object proxy, MethodInfo method, object[] arguments)
{
ParameterInfo[] methodParameters = method.GetParameters();
if (method.Name == nameof(IWin32Services.Select))
{
// select method to find instances
StringBuilder query = new StringBuilder("SELECT * FROM ").Append(this.className).Append(" WHERE ");
for (int i = 0; i < arguments.Length; i++)
{
if (i != 0)
{
query.Append(" AND ");
}
query.Append(' ').Append(Capitalize(methodParameters[i].Name!)).Append(" = '").Append(arguments[i]).Append('\'');
}
using ManagementObjectSearcher searcher = new ManagementObjectSearcher(this.wmiClass.Scope, new ObjectQuery(query.ToString()));
using ManagementObjectCollection results = searcher.Get();
// TODO: support collections
foreach (ManagementObject wmiObject in results)
{
return ProxyFactory.Create(new InstanceHandler(wmiObject), method.ReturnType, true);
}
return null;
}
string methodName = method.Name;
using ManagementBaseObject? wmiParameters = arguments.Length == 0 ? null :
this.GetMethodParameters(this.wmiClass, methodName, methodParameters, arguments);
using ManagementBaseObject result = this.wmiClass.InvokeMethod(methodName, wmiParameters, null);
this.CheckError(result);
return null;
}
}
/// <summary>
/// Obtains an object that corresponds to a table in WMI, which is a collection of a managed object.
/// </summary>
public T GetCollection<T>()
where T : IWmiCollection
{
WmiClassName className = (WmiClassName)typeof(T).GetCustomAttributes(typeof(WmiClassName), false)[0];
return (T)ProxyFactory.Create(new ClassHandler(this.wmiScope, className.Name), typeof(T), true);
}
}
}

144
src/Core/WinSWCore/WmiSchema.cs Executable file → Normal file
View File

@ -1,72 +1,72 @@
namespace WMI
{
public enum ServiceType
{
KernalDriver = 1,
FileSystemDriver = 2,
Adapter = 4,
RecognizerDriver = 8,
OwnProcess = 16,
ShareProcess = 32,
InteractiveProcess = 256,
}
public enum ErrorControl
{
UserNotNotified = 0,
UserNotified = 1,
SystemRestartedWithLastKnownGoodConfiguration = 2,
SystemAttemptsToStartWithAGoodConfiguration = 3
}
public enum StartMode
{
/// <summary>
/// Device driver started by the operating system loader. This value is valid only for driver services.
/// </summary>
Boot,
/// <summary>
/// Device driver started by the operating system initialization process. This value is valid only for driver services.
/// </summary>
System,
/// <summary>
/// Service to be started automatically by the Service Control Manager during system startup.
/// </summary>
Automatic,
/// <summary>
/// Service to be started by the Service Control Manager when a process calls the StartService method.
/// </summary>
Manual,
/// <summary>
/// Service that can no longer be started.
/// </summary>
Disabled,
}
[WmiClassName("Win32_Service")]
public interface IWin32Services : IWmiCollection
{
// ReturnValue Create(bool desktopInteract, string displayName, int errorControl, string loadOrderGroup, string loadOrderGroupDependencies, string name, string pathName, string serviceDependencies, string serviceType, string startMode, string startName, string startPassword);
void Create(string name, string displayName, string pathName, ServiceType serviceType, ErrorControl errorControl, string startMode, bool desktopInteract, string? startName, string? startPassword, string[] serviceDependencies);
void Create(string name, string displayName, string pathName, ServiceType serviceType, ErrorControl errorControl, string startMode, bool desktopInteract, string[] serviceDependencies);
IWin32Service? Select(string name);
}
// https://docs.microsoft.com/windows/win32/cimwin32prov/win32-service
public interface IWin32Service : IWmiObject
{
bool Started { get; }
void Delete();
void StartService();
void StopService();
}
}
namespace WMI
{
public enum ServiceType
{
KernalDriver = 1,
FileSystemDriver = 2,
Adapter = 4,
RecognizerDriver = 8,
OwnProcess = 16,
ShareProcess = 32,
InteractiveProcess = 256,
}
public enum ErrorControl
{
UserNotNotified = 0,
UserNotified = 1,
SystemRestartedWithLastKnownGoodConfiguration = 2,
SystemAttemptsToStartWithAGoodConfiguration = 3
}
public enum StartMode
{
/// <summary>
/// Device driver started by the operating system loader. This value is valid only for driver services.
/// </summary>
Boot,
/// <summary>
/// Device driver started by the operating system initialization process. This value is valid only for driver services.
/// </summary>
System,
/// <summary>
/// Service to be started automatically by the Service Control Manager during system startup.
/// </summary>
Automatic,
/// <summary>
/// Service to be started by the Service Control Manager when a process calls the StartService method.
/// </summary>
Manual,
/// <summary>
/// Service that can no longer be started.
/// </summary>
Disabled,
}
[WmiClassName("Win32_Service")]
public interface IWin32Services : IWmiCollection
{
// ReturnValue Create(bool desktopInteract, string displayName, int errorControl, string loadOrderGroup, string loadOrderGroupDependencies, string name, string pathName, string serviceDependencies, string serviceType, string startMode, string startName, string startPassword);
void Create(string name, string displayName, string pathName, ServiceType serviceType, ErrorControl errorControl, string startMode, bool desktopInteract, string? startName, string? startPassword, string[] serviceDependencies);
void Create(string name, string displayName, string pathName, ServiceType serviceType, ErrorControl errorControl, string startMode, bool desktopInteract, string[] serviceDependencies);
IWin32Service? Select(string name);
}
// https://docs.microsoft.com/windows/win32/cimwin32prov/win32-service
public interface IWin32Service : IWmiObject
{
bool Started { get; }
void Delete();
void StartService();
void StopService();
}
}

View File

@ -1,87 +1,87 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "winsw", "Core\ServiceWrapper\winsw.csproj", "{0DE77F55-ADE5-43C1-999A-0BC81153B039}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "winswTests", "Test\winswTests\winswTests.csproj", "{93843402-842B-44B4-B303-AEE829BE0B43}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharedDirectoryMapper", "Plugins\SharedDirectoryMapper\SharedDirectoryMapper.csproj", "{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{077C2CEC-B687-4B53-86E9-C1A1BF5554E5}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{BC4AD891-E87E-4F30-867C-FD8084A29E5D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{5297623A-1A95-4F89-9AAE-DA634081EC86}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinSWCore", "Core\WinSWCore\WinSWCore.csproj", "{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RunawayProcessKiller", "Plugins\RunawayProcessKiller\RunawayProcessKiller.csproj", "{57284B7A-82A4-407A-B706-EBEA6BF8EA13}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{AA414F46-B863-473A-A0E0-C2971B3396AE}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
..\examples\sample-allOptions.xml = ..\examples\sample-allOptions.xml
..\examples\sample-minimal.xml = ..\examples\sample-minimal.xml
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|Win32 = Debug|Win32
Release|Any CPU = Release|Any CPU
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Debug|Win32.ActiveCfg = Debug|Any CPU
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Debug|Win32.Build.0 = Debug|Any CPU
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Release|Any CPU.Build.0 = Release|Any CPU
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Release|Win32.ActiveCfg = Release|Any CPU
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Release|Win32.Build.0 = Release|Any CPU
{93843402-842B-44B4-B303-AEE829BE0B43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{93843402-842B-44B4-B303-AEE829BE0B43}.Debug|Any CPU.Build.0 = Debug|Any CPU
{93843402-842B-44B4-B303-AEE829BE0B43}.Debug|Win32.ActiveCfg = Debug|Any CPU
{93843402-842B-44B4-B303-AEE829BE0B43}.Debug|Win32.Build.0 = Debug|Any CPU
{93843402-842B-44B4-B303-AEE829BE0B43}.Release|Any CPU.ActiveCfg = Release|Any CPU
{93843402-842B-44B4-B303-AEE829BE0B43}.Release|Any CPU.Build.0 = Release|Any CPU
{93843402-842B-44B4-B303-AEE829BE0B43}.Release|Win32.ActiveCfg = Release|Any CPU
{93843402-842B-44B4-B303-AEE829BE0B43}.Release|Win32.Build.0 = Release|Any CPU
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Debug|Win32.ActiveCfg = Debug|Any CPU
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Debug|Win32.Build.0 = Debug|Any CPU
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Release|Any CPU.Build.0 = Release|Any CPU
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Release|Win32.ActiveCfg = Release|Any CPU
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Release|Win32.Build.0 = Release|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Debug|Win32.ActiveCfg = Debug|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Debug|Win32.Build.0 = Debug|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Release|Any CPU.Build.0 = Release|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Release|Win32.ActiveCfg = Release|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Release|Win32.Build.0 = Release|Any CPU
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Debug|Any CPU.Build.0 = Debug|Any CPU
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Debug|Win32.ActiveCfg = Debug|Any CPU
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Debug|Win32.Build.0 = Debug|Any CPU
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Release|Any CPU.ActiveCfg = Release|Any CPU
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Release|Any CPU.Build.0 = Release|Any CPU
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Release|Win32.ActiveCfg = Release|Any CPU
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Release|Win32.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{0DE77F55-ADE5-43C1-999A-0BC81153B039} = {5297623A-1A95-4F89-9AAE-DA634081EC86}
{93843402-842B-44B4-B303-AEE829BE0B43} = {077C2CEC-B687-4B53-86E9-C1A1BF5554E5}
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5} = {BC4AD891-E87E-4F30-867C-FD8084A29E5D}
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06} = {5297623A-1A95-4F89-9AAE-DA634081EC86}
{57284B7A-82A4-407A-B706-EBEA6BF8EA13} = {BC4AD891-E87E-4F30-867C-FD8084A29E5D}
EndGlobalSection
EndGlobal
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "winsw", "Core\ServiceWrapper\winsw.csproj", "{0DE77F55-ADE5-43C1-999A-0BC81153B039}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "winswTests", "Test\winswTests\winswTests.csproj", "{93843402-842B-44B4-B303-AEE829BE0B43}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharedDirectoryMapper", "Plugins\SharedDirectoryMapper\SharedDirectoryMapper.csproj", "{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{077C2CEC-B687-4B53-86E9-C1A1BF5554E5}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{BC4AD891-E87E-4F30-867C-FD8084A29E5D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{5297623A-1A95-4F89-9AAE-DA634081EC86}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinSWCore", "Core\WinSWCore\WinSWCore.csproj", "{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RunawayProcessKiller", "Plugins\RunawayProcessKiller\RunawayProcessKiller.csproj", "{57284B7A-82A4-407A-B706-EBEA6BF8EA13}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{AA414F46-B863-473A-A0E0-C2971B3396AE}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
..\examples\sample-allOptions.xml = ..\examples\sample-allOptions.xml
..\examples\sample-minimal.xml = ..\examples\sample-minimal.xml
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|Win32 = Debug|Win32
Release|Any CPU = Release|Any CPU
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Debug|Win32.ActiveCfg = Debug|Any CPU
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Debug|Win32.Build.0 = Debug|Any CPU
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Release|Any CPU.Build.0 = Release|Any CPU
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Release|Win32.ActiveCfg = Release|Any CPU
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Release|Win32.Build.0 = Release|Any CPU
{93843402-842B-44B4-B303-AEE829BE0B43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{93843402-842B-44B4-B303-AEE829BE0B43}.Debug|Any CPU.Build.0 = Debug|Any CPU
{93843402-842B-44B4-B303-AEE829BE0B43}.Debug|Win32.ActiveCfg = Debug|Any CPU
{93843402-842B-44B4-B303-AEE829BE0B43}.Debug|Win32.Build.0 = Debug|Any CPU
{93843402-842B-44B4-B303-AEE829BE0B43}.Release|Any CPU.ActiveCfg = Release|Any CPU
{93843402-842B-44B4-B303-AEE829BE0B43}.Release|Any CPU.Build.0 = Release|Any CPU
{93843402-842B-44B4-B303-AEE829BE0B43}.Release|Win32.ActiveCfg = Release|Any CPU
{93843402-842B-44B4-B303-AEE829BE0B43}.Release|Win32.Build.0 = Release|Any CPU
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Debug|Win32.ActiveCfg = Debug|Any CPU
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Debug|Win32.Build.0 = Debug|Any CPU
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Release|Any CPU.Build.0 = Release|Any CPU
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Release|Win32.ActiveCfg = Release|Any CPU
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Release|Win32.Build.0 = Release|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Debug|Win32.ActiveCfg = Debug|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Debug|Win32.Build.0 = Debug|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Release|Any CPU.Build.0 = Release|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Release|Win32.ActiveCfg = Release|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Release|Win32.Build.0 = Release|Any CPU
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Debug|Any CPU.Build.0 = Debug|Any CPU
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Debug|Win32.ActiveCfg = Debug|Any CPU
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Debug|Win32.Build.0 = Debug|Any CPU
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Release|Any CPU.ActiveCfg = Release|Any CPU
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Release|Any CPU.Build.0 = Release|Any CPU
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Release|Win32.ActiveCfg = Release|Any CPU
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Release|Win32.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{0DE77F55-ADE5-43C1-999A-0BC81153B039} = {5297623A-1A95-4F89-9AAE-DA634081EC86}
{93843402-842B-44B4-B303-AEE829BE0B43} = {077C2CEC-B687-4B53-86E9-C1A1BF5554E5}
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5} = {BC4AD891-E87E-4F30-867C-FD8084A29E5D}
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06} = {5297623A-1A95-4F89-9AAE-DA634081EC86}
{57284B7A-82A4-407A-B706-EBEA6BF8EA13} = {BC4AD891-E87E-4F30-867C-FD8084A29E5D}
EndGlobalSection
EndGlobal