using System;
using System.Runtime.InteropServices;
namespace Installer;
internal class SafeServiceHandle : SafeHandle
{
public override Boolean IsInvalid
{
get
{
if (!(DangerousGetHandle() == IntPtr.Zero))
{
return DangerousGetHandle() == new IntPtr(-1);
}
return true;
}
}
internal SafeServiceHandle(IntPtr handle)
: base(IntPtr.Zero, true) => SetHandle(handle);
protected override Boolean ReleaseHandle() => Advapi32.CloseServiceHandle(handle);
}
internal class Advapi32
{
[Flags]
public enum ServiceType
{
Adapter = 0x4,
FileSystemDriver = 0x2,
InteractiveProcess = 0x100,
KernelDriver = 0x1,
RecognizerDriver = 0x8,
Win32OwnProcess = 0x10,
Win32ShareProcess = 0x20
}
internal enum ControlOptions
{
Stop = 1,
Pause = 2,
Continue = 3,
Interrogate = 4,
Shutdown = 5,
PowerEvent = 13,
SessionChange = 14,
TimeChange = 16,
}
internal class ServiceOptions
{
internal const Int32 SERVICE_QUERY_CONFIG = 1;
internal const Int32 SERVICE_CHANGE_CONFIG = 2;
internal const Int32 SERVICE_QUERY_STATUS = 4;
internal const Int32 SERVICE_ENUMERATE_DEPENDENTS = 8;
internal const Int32 SERVICE_START = 16;
internal const Int32 SERVICE_STOP = 32;
internal const Int32 SERVICE_PAUSE_CONTINUE = 64;
internal const Int32 SERVICE_INTERROGATE = 128;
internal const Int32 SERVICE_USER_DEFINED_CONTROL = 256;
internal const Int32 SERVICE_ALL_ACCESS = 983551;
internal const Int32 STANDARD_RIGHTS_DELETE = 65536;
internal const Int32 STANDARD_RIGHTS_REQUIRED = 983040;
}
internal class ServiceControllerOptions
{
internal const Int32 SC_ENUM_PROCESS_INFO = 0;
internal const Int32 SC_MANAGER_CONNECT = 1;
internal const Int32 SC_MANAGER_CREATE_SERVICE = 2;
internal const Int32 SC_MANAGER_ENUMERATE_SERVICE = 4;
internal const Int32 SC_MANAGER_LOCK = 8;
internal const Int32 SC_MANAGER_MODIFY_BOOT_CONFIG = 32;
internal const Int32 SC_MANAGER_QUERY_LOCK_STATUS = 16;
internal const Int32 SC_MANAGER_ALL = 983103;
}
internal struct SERVICE_STATUS
{
public ServiceType serviceType;
public ServiceControllerStatus currentState;
public ControlsAccepted controlsAccepted;
public Int32 win32ExitCode;
public Int32 serviceSpecificExitCode;
public Int32 checkPoint;
public Int32 waitHint;
}
public enum ServiceControllerStatus : Int32
{
ContinuePending = 5,
Paused = 7,
PausePending = 6,
Running = 4,
StartPending = 2,
Stopped = 1,
StopPending = 3
}
[Flags]
public enum ControlsAccepted : Int32
{
NetBindChange = 0x00000010,
ParamChange = 0x00000008,
CanPauseAndContinue = 0x00000002,
/// <summary>系统将关闭</summary>
PreShutdown = 0x00000100,
CanShutdown = 0x00000004,
CanStop = 0x00000001,
//supported only by HandlerEx
HardwareProfileChange = 0x00000020,
/// <summary>电源状态更改</summary>
CanHandlePowerEvent = 0x00000040,
/// <summary>会话状态发生更改</summary>
CanHandleSessionChangeEvent = 0x00000080,
/// <summary>系统时间已更改</summary>
TimeChange = 0x00000200,
/// <summary>注册为已发生事件的服务触发事件</summary>
TriggerEvent = 0x00000400,
/// <summary>用户已开始重新启动</summary>
UserModeReboot = 0x00000800
}
public delegate void ServiceMainCallback(Int32 argCount, IntPtr argPointer);
[StructLayout(LayoutKind.Sequential)]
public class SERVICE_TABLE_ENTRY
{
public IntPtr name;
public ServiceMainCallback callback;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SERVICE_DESCRIPTION
{
public IntPtr Description;
}
public enum PowerBroadcastStatus
{
BatteryLow = 9,
OemEvent = 11,
PowerStatusChange = 10,
QuerySuspend = 0,
QuerySuspendFailed = 2,
ResumeAutomatic = 18,
ResumeCritical = 6,
ResumeSuspend = 7,
Suspend = 4
}
public enum SessionChangeReason
{
ConsoleConnect = 1,
ConsoleDisconnect,
RemoteConnect,
RemoteDisconnect,
SessionLogon,
SessionLogoff,
SessionLock,
SessionUnlock,
SessionRemoteControl
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public class WTSSESSION_NOTIFICATION
{
public Int32 size;
public Int32 sessionId;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public class SERVICE_TIMECHANGE_INFO
{
public Int64 NewTime;
public Int64 OldTime;
}
public delegate Int32 ServiceControlCallbackEx(ControlOptions control, Int32 eventType, IntPtr eventData, IntPtr eventContext);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern Boolean CloseServiceHandle(IntPtr handle);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern unsafe Boolean ControlService(SafeServiceHandle serviceHandle, ControlOptions control, SERVICE_STATUS* pStatus);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, EntryPoint = "OpenSCManagerW", SetLastError = true)]
internal static extern IntPtr OpenSCManager(String machineName, String databaseName, Int32 access);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, EntryPoint = "OpenServiceW", SetLastError = true)]
internal static extern IntPtr OpenService(SafeServiceHandle databaseHandle, String serviceName, Int32 access);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern IntPtr CreateService(SafeServiceHandle databaseHandle, String lpSvcName, String lpDisplayName,
Int32 dwDesiredAccess, Int32 dwServiceType, Int32 dwStartType,
Int32 dwErrorControl, String lpPathName, String lpLoadOrderGroup,
Int32 lpdwTagId, String lpDependencies, String lpServiceStartName,
String lpPassword);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern Int32 DeleteService(SafeServiceHandle serviceHandle);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern unsafe Boolean QueryServiceStatus(SafeServiceHandle serviceHandle, SERVICE_STATUS* pStatus);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, EntryPoint = "StartServiceW", SetLastError = true)]
internal static extern Boolean StartService(SafeServiceHandle serviceHandle, Int32 argNum, IntPtr argPtrs);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern unsafe Boolean SetServiceStatus(IntPtr serviceStatusHandle, SERVICE_STATUS* status);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr RegisterServiceCtrlHandlerEx(String serviceName, ServiceControlCallbackEx callback, IntPtr userData);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern Boolean StartServiceCtrlDispatcher(IntPtr entry);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern Boolean ChangeServiceConfig2(SafeServiceHandle serviceHandle, Int32 dwInfoLevel, IntPtr pInfo);
}
|