diff --git a/src/WinSW.Core/Native/Service.cs b/src/WinSW.Core/Native/Service.cs index 85f4e19..3700cf8 100644 --- a/src/WinSW.Core/Native/Service.cs +++ b/src/WinSW.Core/Native/Service.cs @@ -117,9 +117,9 @@ namespace WinSW.Native } /// - internal Service OpenService(string serviceName) + internal Service OpenService(string serviceName, ServiceAccess access = ServiceAccess.ALL_ACCESS) { - IntPtr serviceHandle = ServiceApis.OpenService(this.handle, serviceName, ServiceAccess.ALL_ACCESS); + IntPtr serviceHandle = ServiceApis.OpenService(this.handle, serviceName, access); if (serviceHandle == IntPtr.Zero) { Throw.Command.Win32Exception("Failed to open the service."); @@ -171,6 +171,24 @@ namespace WinSW.Native } } + /// + internal void SetStatus(IntPtr statusHandle, ServiceControllerStatus state) + { + if (!QueryServiceStatus(this.handle, out SERVICE_STATUS status)) + { + Throw.Command.Win32Exception("Failed to query service status."); + } + + status.CheckPoint = 0; + status.WaitHint = 0; + status.CurrentState = state; + + if (!SetServiceStatus(statusHandle, status)) + { + Throw.Command.Win32Exception("Failed to set service status."); + } + } + /// internal void Delete() { diff --git a/src/WinSW.Core/Native/ServiceApis.cs b/src/WinSW.Core/Native/ServiceApis.cs index d547ad4..be95d0e 100644 --- a/src/WinSW.Core/Native/ServiceApis.cs +++ b/src/WinSW.Core/Native/ServiceApis.cs @@ -51,7 +51,7 @@ namespace WinSW.Native [DllImport(Libraries.Advapi32, SetLastError = true)] internal static extern bool SetServiceObjectSecurity(IntPtr serviceHandle, SecurityInfos securityInformation, byte[] securityDescriptor); - [DllImport(Libraries.Advapi32)] + [DllImport(Libraries.Advapi32, SetLastError = true)] internal static extern bool SetServiceStatus(IntPtr serviceStatusHandle, in SERVICE_STATUS serviceStatus); // SERVICE_ @@ -152,7 +152,7 @@ namespace WinSW.Native internal struct SERVICE_STATUS { - public int ServiceType; + public ServiceType ServiceType; public ServiceControllerStatus CurrentState; public int ControlsAccepted; public int Win32ExitCode; diff --git a/src/WinSW/WrapperService.cs b/src/WinSW/WrapperService.cs index ca339ea..e9ce54f 100644 --- a/src/WinSW/WrapperService.cs +++ b/src/WinSW/WrapperService.cs @@ -17,8 +17,6 @@ namespace WinSW { public class WrapperService : ServiceBase, IEventLogger { - private ServiceApis.SERVICE_STATUS wrapperServiceStatus; - private readonly Process process = new Process(); private readonly ServiceDescriptor descriptor; private Dictionary? envs; @@ -415,13 +413,12 @@ namespace WinSW this.RequestAdditionalTime(serviceWaitHint); } - private void SignalShutdownComplete() + private void SignalStopped() { - IntPtr handle = this.ServiceHandle; - this.wrapperServiceStatus.CheckPoint++; - // WriteEvent("SignalShutdownComplete " + wrapperServiceStatus.checkPoint + ":" + wrapperServiceStatus.waitHint); - this.wrapperServiceStatus.CurrentState = ServiceControllerStatus.Stopped; - ServiceApis.SetServiceStatus(handle, this.wrapperServiceStatus); + using ServiceManager scm = ServiceManager.Open(); + using Service sc = scm.OpenService(this.ServiceName, ServiceApis.ServiceAccess.QUERY_STATUS); + + sc.SetStatus(this.ServiceHandle, ServiceControllerStatus.Stopped); } private void StartProcess(Process processToStart, string arguments, string executable, LogHandler? logHandler, bool redirectStdin) @@ -442,12 +439,17 @@ namespace WinSW // if we finished orderly, report that to SCM. // by not reporting unclean shutdown, we let Windows SCM to decide if it wants to // restart the service automatically - if (process.ExitCode == 0) + try { - this.SignalShutdownComplete(); + if (process.ExitCode == 0) + { + this.SignalStopped(); + } + } + finally + { + Environment.Exit(process.ExitCode); } - - Environment.Exit(process.ExitCode); } }