From 89677a7f4982adef4f85638a840cc31cb81887b8 Mon Sep 17 00:00:00 2001 From: NextTurn <45985406+NextTurn@users.noreply.github.com> Date: Fri, 7 Feb 2020 00:00:00 +0800 Subject: [PATCH 01/13] Support 'If-Modified-Since' for downloads --- src/Core/WinSWCore/Download.cs | 68 ++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/src/Core/WinSWCore/Download.cs b/src/Core/WinSWCore/Download.cs index 69b8dae..ff0ba09 100755 --- a/src/Core/WinSWCore/Download.cs +++ b/src/Core/WinSWCore/Download.cs @@ -6,9 +6,7 @@ using System.Text; using System.Threading.Tasks; #endif using System.Xml; -#if !VNEXT using log4net; -#endif using winsw.Util; namespace winsw @@ -26,9 +24,7 @@ namespace winsw basic } -#if !VNEXT private static readonly ILog Logger = LogManager.GetLogger(typeof(Download)); -#endif public readonly string From; public readonly string To; @@ -163,25 +159,57 @@ namespace winsw throw new WebException("Code defect. Unsupported authentication type: " + Auth); } - string tmpFilePath = To + ".tmp"; -#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)) + bool supportsIfModifiedSince = false; + if (request is HttpWebRequest httpRequest && File.Exists(To)) { -#if VNEXT - await responseStream.CopyToAsync(tmpStream); -#elif NET20 - CopyStream(responseStream, tmpStream); -#else - responseStream.CopyTo(tmpStream); -#endif + supportsIfModifiedSince = true; + httpRequest.IfModifiedSince = File.GetLastWriteTime(To); } - FileHelper.MoveOrReplaceFile(To + ".tmp", To); + DateTime lastModified = default; + string tmpFilePath = 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(To + ".tmp", To); + + if (supportsIfModifiedSince) + { + File.SetLastWriteTime(To, lastModified); + } + } + catch (WebException e) + { + if (supportsIfModifiedSince && ((HttpWebResponse)e.Response).StatusCode == HttpStatusCode.NotModified) + { + Logger.Info($"Skipped downloading unmodified resource '{From}'"); + } + else + { + throw; + } + } } #if NET20 From 3bb10ab60d3a2f1cf792c5b32f0513a4217270ba Mon Sep 17 00:00:00 2001 From: NextTurn <45985406+NextTurn@users.noreply.github.com> Date: Sun, 2 Dec 2018 00:00:00 +0800 Subject: [PATCH 02/13] Remove unnecessary attributes --- src/Core/WinSWCore/Native/Advapi32.cs | 13 +++---------- src/Core/WinSWCore/Util/SigIntHelper.cs | 3 +-- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/Core/WinSWCore/Native/Advapi32.cs b/src/Core/WinSWCore/Native/Advapi32.cs index 75f1804..7b70095 100755 --- a/src/Core/WinSWCore/Native/Advapi32.cs +++ b/src/Core/WinSWCore/Native/Advapi32.cs @@ -274,15 +274,12 @@ namespace winsw.Native public class Advapi32 { [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool ChangeServiceConfig2(IntPtr hService, SERVICE_CONFIG_INFOLEVEL dwInfoLevel, IntPtr lpInfo); [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool ChangeServiceConfig2(IntPtr hService, SERVICE_CONFIG_INFOLEVEL dwInfoLevel, ref SERVICE_FAILURE_ACTIONS sfa); [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool ChangeServiceConfig2(IntPtr hService, SERVICE_CONFIG_INFOLEVEL dwInfoLevel, ref SERVICE_DELAYED_AUTO_START sfa); [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] @@ -292,23 +289,22 @@ namespace winsw.Native internal static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess); [DllImport("advapi32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool CloseServiceHandle(IntPtr hSCObject); [DllImport("advapi32.DLL")] public static extern bool SetServiceStatus(IntPtr hServiceStatus, ref SERVICE_STATUS lpServiceStatus); - [DllImport("advapi32.dll", PreserveSig = true)] + [DllImport("advapi32.dll")] internal static extern uint LsaOpenPolicy(ref LSA_UNICODE_STRING SystemName, ref LSA_OBJECT_ATTRIBUTES ObjectAttributes, int DesiredAccess, out IntPtr PolicyHandle); - [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)] + [DllImport("advapi32.dll", SetLastError = true)] internal static extern uint LsaAddAccountRights(IntPtr PolicyHandle, IntPtr AccountSid, LSA_UNICODE_STRING[] UserRights, uint CountOfRights); [DllImport("advapi32")] internal static extern void FreeSid(IntPtr pSid); - [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true, PreserveSig = true)] + [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] internal static extern bool LookupAccountName(string lpSystemName, string lpAccountName, IntPtr psid, ref int cbsid, StringBuilder domainName, ref int cbdomainLength, ref int use); @@ -584,9 +580,7 @@ namespace winsw.Native /// public int dwResetPeriod; - [MarshalAs(UnmanagedType.LPWStr)] public string lpRebootMsg; - [MarshalAs(UnmanagedType.LPWStr)] public string lpCommand; public int cActions; public IntPtr/*SC_ACTION[]*/ lpsaActions; @@ -596,7 +590,6 @@ namespace winsw.Native [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct SERVICE_DELAYED_AUTO_START { - [MarshalAs(UnmanagedType.Bool)] public bool fDelayedAutostart; } } diff --git a/src/Core/WinSWCore/Util/SigIntHelper.cs b/src/Core/WinSWCore/Util/SigIntHelper.cs index 801539b..3acc949 100644 --- a/src/Core/WinSWCore/Util/SigIntHelper.cs +++ b/src/Core/WinSWCore/Util/SigIntHelper.cs @@ -15,7 +15,7 @@ namespace winsw.Util [DllImport(KERNEL32, SetLastError = true)] private static extern bool AttachConsole(uint dwProcessId); - [DllImport(KERNEL32, SetLastError = true, ExactSpelling = true)] + [DllImport(KERNEL32, SetLastError = true)] private static extern bool FreeConsole(); [DllImport(KERNEL32)] @@ -35,7 +35,6 @@ namespace winsw.Util } [DllImport(KERNEL32)] - [return: MarshalAs(UnmanagedType.Bool)] private static extern bool GenerateConsoleCtrlEvent(CtrlTypes dwCtrlEvent, uint dwProcessGroupId); /// From f1036e613b10849bdc475ddd7ab0097b5dec7d0a Mon Sep 17 00:00:00 2001 From: NextTurn <45985406+NextTurn@users.noreply.github.com> Date: Sun, 2 Dec 2018 00:00:00 +0800 Subject: [PATCH 03/13] Replace GetLastError --- src/Core/WinSWCore/Native/Advapi32.cs | 2 +- src/Core/WinSWCore/Native/Kernel32.cs | 3 --- src/Core/WinSWCore/Util/SigIntHelper.cs | 3 +-- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Core/WinSWCore/Native/Advapi32.cs b/src/Core/WinSWCore/Native/Advapi32.cs index 7b70095..9efb32c 100755 --- a/src/Core/WinSWCore/Native/Advapi32.cs +++ b/src/Core/WinSWCore/Native/Advapi32.cs @@ -195,7 +195,7 @@ namespace winsw.Native if (!result) { - winErrorCode = Kernel32.GetLastError(); + winErrorCode = Marshal.GetLastWin32Error(); Console.WriteLine("LookupAccountName failed: " + winErrorCode); } else diff --git a/src/Core/WinSWCore/Native/Kernel32.cs b/src/Core/WinSWCore/Native/Kernel32.cs index 14dd870..1193406 100755 --- a/src/Core/WinSWCore/Native/Kernel32.cs +++ b/src/Core/WinSWCore/Native/Kernel32.cs @@ -24,9 +24,6 @@ namespace winsw.Native string? lpCurrentDirectory, [In] ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation); - - [DllImport("kernel32.dll")] - public static extern int GetLastError(); } [StructLayout(LayoutKind.Sequential)] diff --git a/src/Core/WinSWCore/Util/SigIntHelper.cs b/src/Core/WinSWCore/Util/SigIntHelper.cs index 3acc949..11f8f65 100644 --- a/src/Core/WinSWCore/Util/SigIntHelper.cs +++ b/src/Core/WinSWCore/Util/SigIntHelper.cs @@ -2,7 +2,6 @@ using System.Diagnostics; using System.Runtime.InteropServices; using log4net; -using winsw.Native; namespace winsw.Util { @@ -57,7 +56,7 @@ namespace winsw.Util bool success = FreeConsole(); if (!success) { - long errorCode = Kernel32.GetLastError(); + long errorCode = Marshal.GetLastWin32Error(); Logger.Warn("Failed to detach from console. Error code: " + errorCode); } From 5bc19e43af32afad383f9ed4f62f22b0255d6093 Mon Sep 17 00:00:00 2001 From: NextTurn <45985406+NextTurn@users.noreply.github.com> Date: Sun, 2 Dec 2018 00:00:00 +0800 Subject: [PATCH 04/13] Introduce constant strings --- src/Core/WinSWCore/Native/Advapi32.cs | 30 +++++++++++++------------ src/Core/WinSWCore/Native/Kernel32.cs | 6 +++-- src/Core/WinSWCore/Util/SigIntHelper.cs | 10 ++++----- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/src/Core/WinSWCore/Native/Advapi32.cs b/src/Core/WinSWCore/Native/Advapi32.cs index 9efb32c..4289edd 100755 --- a/src/Core/WinSWCore/Native/Advapi32.cs +++ b/src/Core/WinSWCore/Native/Advapi32.cs @@ -273,48 +273,50 @@ namespace winsw.Native /// public class Advapi32 { - [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + private const string Advapi32LibraryName = "advapi32.dll"; + + [DllImport(Advapi32LibraryName, SetLastError = true, CharSet = CharSet.Unicode)] internal static extern bool ChangeServiceConfig2(IntPtr hService, SERVICE_CONFIG_INFOLEVEL dwInfoLevel, IntPtr lpInfo); - [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + [DllImport(Advapi32LibraryName, SetLastError = true, CharSet = CharSet.Unicode)] internal static extern bool ChangeServiceConfig2(IntPtr hService, SERVICE_CONFIG_INFOLEVEL dwInfoLevel, ref SERVICE_FAILURE_ACTIONS sfa); - [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + [DllImport(Advapi32LibraryName, SetLastError = true, CharSet = CharSet.Unicode)] internal static extern bool ChangeServiceConfig2(IntPtr hService, SERVICE_CONFIG_INFOLEVEL dwInfoLevel, ref SERVICE_DELAYED_AUTO_START sfa); - [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + [DllImport(Advapi32LibraryName, SetLastError = true, CharSet = CharSet.Unicode)] internal static extern IntPtr OpenSCManager(string? machineName, string? databaseName, uint dwAccess); - [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + [DllImport(Advapi32LibraryName, SetLastError = true, CharSet = CharSet.Unicode)] internal static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess); - [DllImport("advapi32.dll", SetLastError = true)] + [DllImport(Advapi32LibraryName, SetLastError = true)] internal static extern bool CloseServiceHandle(IntPtr hSCObject); - [DllImport("advapi32.DLL")] + [DllImport(Advapi32LibraryName)] public static extern bool SetServiceStatus(IntPtr hServiceStatus, ref SERVICE_STATUS lpServiceStatus); - [DllImport("advapi32.dll")] + [DllImport(Advapi32LibraryName)] internal static extern uint LsaOpenPolicy(ref LSA_UNICODE_STRING SystemName, ref LSA_OBJECT_ATTRIBUTES ObjectAttributes, int DesiredAccess, out IntPtr PolicyHandle); - [DllImport("advapi32.dll", SetLastError = true)] + [DllImport(Advapi32LibraryName, SetLastError = true)] internal static extern uint LsaAddAccountRights(IntPtr PolicyHandle, IntPtr AccountSid, LSA_UNICODE_STRING[] UserRights, uint CountOfRights); - [DllImport("advapi32")] + [DllImport(Advapi32LibraryName)] internal static extern void FreeSid(IntPtr pSid); - [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] + [DllImport(Advapi32LibraryName, CharSet = CharSet.Auto, SetLastError = true)] internal static extern bool LookupAccountName(string lpSystemName, string lpAccountName, IntPtr psid, ref int cbsid, StringBuilder domainName, ref int cbdomainLength, ref int use); - [DllImport("advapi32.dll")] + [DllImport(Advapi32LibraryName)] internal static extern bool IsValidSid(IntPtr pSid); - [DllImport("advapi32.dll", SetLastError = true)] + [DllImport(Advapi32LibraryName, SetLastError = true)] internal static extern uint LsaClose(IntPtr ObjectHandle); - [DllImport("advapi32.dll", SetLastError = false)] + [DllImport(Advapi32LibraryName, SetLastError = false)] internal static extern uint LsaNtStatusToWinError(uint status); } diff --git a/src/Core/WinSWCore/Native/Kernel32.cs b/src/Core/WinSWCore/Native/Kernel32.cs index 1193406..bf323db 100755 --- a/src/Core/WinSWCore/Native/Kernel32.cs +++ b/src/Core/WinSWCore/Native/Kernel32.cs @@ -9,10 +9,12 @@ namespace winsw.Native /// public class Kernel32 { - [DllImport("kernel32.dll", SetLastError = true)] + private const string Kernel32LibraryName = "kernel32.dll"; + + [DllImport(Kernel32LibraryName, SetLastError = true)] public static extern bool SetStdHandle(int nStdHandle, SafeFileHandle handle); - [DllImport("kernel32.dll", SetLastError = true)] + [DllImport(Kernel32LibraryName, SetLastError = true)] public static extern bool CreateProcess( string? lpApplicationName, string lpCommandLine, diff --git a/src/Core/WinSWCore/Util/SigIntHelper.cs b/src/Core/WinSWCore/Util/SigIntHelper.cs index 11f8f65..c915d19 100644 --- a/src/Core/WinSWCore/Util/SigIntHelper.cs +++ b/src/Core/WinSWCore/Util/SigIntHelper.cs @@ -9,15 +9,15 @@ namespace winsw.Util { private static readonly ILog Logger = LogManager.GetLogger(typeof(SigIntHelper)); - private const string KERNEL32 = "kernel32.dll"; + private const string Kernel32LibraryName = "kernel32.dll"; - [DllImport(KERNEL32, SetLastError = true)] + [DllImport(Kernel32LibraryName, SetLastError = true)] private static extern bool AttachConsole(uint dwProcessId); - [DllImport(KERNEL32, SetLastError = true)] + [DllImport(Kernel32LibraryName, SetLastError = true)] private static extern bool FreeConsole(); - [DllImport(KERNEL32)] + [DllImport(Kernel32LibraryName)] private static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate? HandlerRoutine, bool Add); // Delegate type to be used as the Handler Routine for SCCH @@ -33,7 +33,7 @@ namespace winsw.Util CTRL_SHUTDOWN_EVENT } - [DllImport(KERNEL32)] + [DllImport(Kernel32LibraryName)] private static extern bool GenerateConsoleCtrlEvent(CtrlTypes dwCtrlEvent, uint dwProcessGroupId); /// From fc08355620d67b1eba645d016964eb2558e874d1 Mon Sep 17 00:00:00 2001 From: NextTurn <45985406+NextTurn@users.noreply.github.com> Date: Sun, 2 Dec 2018 00:00:00 +0800 Subject: [PATCH 05/13] Specify Unicode versions --- src/Core/WinSWCore/Native/Advapi32.cs | 12 ++++++------ src/Core/WinSWCore/Native/Kernel32.cs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Core/WinSWCore/Native/Advapi32.cs b/src/Core/WinSWCore/Native/Advapi32.cs index 4289edd..e83ae6d 100755 --- a/src/Core/WinSWCore/Native/Advapi32.cs +++ b/src/Core/WinSWCore/Native/Advapi32.cs @@ -275,19 +275,19 @@ namespace winsw.Native { private const string Advapi32LibraryName = "advapi32.dll"; - [DllImport(Advapi32LibraryName, SetLastError = true, CharSet = CharSet.Unicode)] + [DllImport(Advapi32LibraryName, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "ChangeServiceConfig2W")] internal static extern bool ChangeServiceConfig2(IntPtr hService, SERVICE_CONFIG_INFOLEVEL dwInfoLevel, IntPtr lpInfo); - [DllImport(Advapi32LibraryName, SetLastError = true, CharSet = CharSet.Unicode)] + [DllImport(Advapi32LibraryName, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "ChangeServiceConfig2W")] internal static extern bool ChangeServiceConfig2(IntPtr hService, SERVICE_CONFIG_INFOLEVEL dwInfoLevel, ref SERVICE_FAILURE_ACTIONS sfa); - [DllImport(Advapi32LibraryName, SetLastError = true, CharSet = CharSet.Unicode)] + [DllImport(Advapi32LibraryName, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "ChangeServiceConfig2W")] internal static extern bool ChangeServiceConfig2(IntPtr hService, SERVICE_CONFIG_INFOLEVEL dwInfoLevel, ref SERVICE_DELAYED_AUTO_START sfa); - [DllImport(Advapi32LibraryName, SetLastError = true, CharSet = CharSet.Unicode)] + [DllImport(Advapi32LibraryName, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "OpenSCManagerW")] internal static extern IntPtr OpenSCManager(string? machineName, string? databaseName, uint dwAccess); - [DllImport(Advapi32LibraryName, SetLastError = true, CharSet = CharSet.Unicode)] + [DllImport(Advapi32LibraryName, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "OpenServiceW")] internal static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess); [DllImport(Advapi32LibraryName, SetLastError = true)] @@ -306,7 +306,7 @@ namespace winsw.Native [DllImport(Advapi32LibraryName)] internal static extern void FreeSid(IntPtr pSid); - [DllImport(Advapi32LibraryName, CharSet = CharSet.Auto, SetLastError = true)] + [DllImport(Advapi32LibraryName, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "LookupAccountNameW")] internal static extern bool LookupAccountName(string lpSystemName, string lpAccountName, IntPtr psid, ref int cbsid, StringBuilder domainName, ref int cbdomainLength, ref int use); diff --git a/src/Core/WinSWCore/Native/Kernel32.cs b/src/Core/WinSWCore/Native/Kernel32.cs index bf323db..73d29b9 100755 --- a/src/Core/WinSWCore/Native/Kernel32.cs +++ b/src/Core/WinSWCore/Native/Kernel32.cs @@ -14,7 +14,7 @@ namespace winsw.Native [DllImport(Kernel32LibraryName, SetLastError = true)] public static extern bool SetStdHandle(int nStdHandle, SafeFileHandle handle); - [DllImport(Kernel32LibraryName, SetLastError = true)] + [DllImport(Kernel32LibraryName, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "CreateProcessW")] public static extern bool CreateProcess( string? lpApplicationName, string lpCommandLine, From 05b421b37be97ded707b3ae4430fcb0d16ce6f52 Mon Sep 17 00:00:00 2001 From: NextTurn <45985406+NextTurn@users.noreply.github.com> Date: Mon, 3 Dec 2018 00:00:00 +0800 Subject: [PATCH 06/13] Remove unused file --- src/Core/ServiceWrapper/SigIntHelper.cs | 59 ------------------------- 1 file changed, 59 deletions(-) delete mode 100644 src/Core/ServiceWrapper/SigIntHelper.cs diff --git a/src/Core/ServiceWrapper/SigIntHelper.cs b/src/Core/ServiceWrapper/SigIntHelper.cs deleted file mode 100644 index 4134740..0000000 --- a/src/Core/ServiceWrapper/SigIntHelper.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.Diagnostics; -using System.Runtime.InteropServices; - -namespace winsw -{ - public static class SigIntHelper - { - private const string KERNEL32 = "kernel32.dll"; - - [DllImport(KERNEL32, SetLastError = true)] - private static extern bool AttachConsole(uint dwProcessId); - - [DllImport(KERNEL32, SetLastError = true, ExactSpelling = true)] - private static extern bool FreeConsole(); - - [DllImport(KERNEL32)] - private static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate? HandlerRoutine, bool Add); - - // Delegate type to be used as the Handler Routine for SCCH - private delegate bool ConsoleCtrlDelegate(CtrlTypes CtrlType); - - // Enumerated type for the control messages sent to the handler routine - private enum CtrlTypes : uint - { - CTRL_C_EVENT = 0, - CTRL_BREAK_EVENT, - CTRL_CLOSE_EVENT, - CTRL_LOGOFF_EVENT = 5, - CTRL_SHUTDOWN_EVENT - } - - [DllImport(KERNEL32)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool GenerateConsoleCtrlEvent(CtrlTypes dwCtrlEvent, uint dwProcessGroupId); - - /// - /// Uses the native funciton "AttachConsole" to attach the thread to the executing process to try to trigger a CTRL_C event (SIGINT). If the application - /// doesn't honor the event and shut down gracefully, the. wait period will time out after 15 seconds. - /// - /// The process to attach to and send the SIGINT - /// True if the process shut down successfully to the SIGINT, false if it did not. - public static bool SendSIGINTToProcess(Process process, TimeSpan shutdownTimeout) - { - if (AttachConsole((uint)process.Id)) - { - // Disable Ctrl-C handling for our program - SetConsoleCtrlHandler(null, true); - GenerateConsoleCtrlEvent(CtrlTypes.CTRL_C_EVENT, 0); - - process.WaitForExit((int)shutdownTimeout.TotalMilliseconds); - - return process.HasExited; - } - - return false; - } - } -} From 80e99d8426fedf3ef2ad70066f6087f8b05c55e7 Mon Sep 17 00:00:00 2001 From: NextTurn <45985406+NextTurn@users.noreply.github.com> Date: Mon, 3 Dec 2018 00:00:00 +0800 Subject: [PATCH 07/13] Rework P/Invoke signatures --- src/Core/ServiceWrapper/Main.cs | 7 ++- src/Core/WinSWCore/Native/Advapi32.cs | 57 +++++++++++-------------- src/Core/WinSWCore/Native/Kernel32.cs | 6 ++- src/Core/WinSWCore/Util/SigIntHelper.cs | 4 +- 4 files changed, 33 insertions(+), 41 deletions(-) diff --git a/src/Core/ServiceWrapper/Main.cs b/src/Core/ServiceWrapper/Main.cs index a56ae4d..1aa2476 100644 --- a/src/Core/ServiceWrapper/Main.cs +++ b/src/Core/ServiceWrapper/Main.cs @@ -426,7 +426,7 @@ namespace winsw _wrapperServiceStatus.waitHint = effectiveWaitHint; // WriteEvent("SignalShutdownPending " + wrapperServiceStatus.checkPoint + ":" + wrapperServiceStatus.waitHint); _wrapperServiceStatus.currentState = (int)State.SERVICE_STOP_PENDING; - Advapi32.SetServiceStatus(handle, ref _wrapperServiceStatus); + Advapi32.SetServiceStatus(handle, _wrapperServiceStatus); } private void SignalShutdownComplete() @@ -435,7 +435,7 @@ namespace winsw _wrapperServiceStatus.checkPoint++; // WriteEvent("SignalShutdownComplete " + wrapperServiceStatus.checkPoint + ":" + wrapperServiceStatus.waitHint); _wrapperServiceStatus.currentState = (int)State.SERVICE_STOPPED; - Advapi32.SetServiceStatus(handle, ref _wrapperServiceStatus); + Advapi32.SetServiceStatus(handle, _wrapperServiceStatus); } private void StartProcess(Process processToStart, string arguments, string executable, LogHandler? logHandler, bool redirectStdin) @@ -796,8 +796,7 @@ namespace winsw // run restart from another process group. see README.md for why this is useful. - STARTUPINFO si = default; - bool result = Kernel32.CreateProcess(null, descriptor.ExecutablePath + " restart", IntPtr.Zero, IntPtr.Zero, false, 0x200/*CREATE_NEW_PROCESS_GROUP*/, IntPtr.Zero, null, ref si, out _); + bool result = Kernel32.CreateProcess(null, descriptor.ExecutablePath + " restart", IntPtr.Zero, IntPtr.Zero, false, Kernel32.CREATE_NEW_PROCESS_GROUP, IntPtr.Zero, null, default, out _); if (!result) { throw new Exception("Failed to invoke restart: " + Marshal.GetLastWin32Error()); diff --git a/src/Core/WinSWCore/Native/Advapi32.cs b/src/Core/WinSWCore/Native/Advapi32.cs index e83ae6d..10d3c34 100755 --- a/src/Core/WinSWCore/Native/Advapi32.cs +++ b/src/Core/WinSWCore/Native/Advapi32.cs @@ -35,7 +35,7 @@ namespace winsw.Native public void Dispose() { if (_handle != IntPtr.Zero) - Advapi32.CloseServiceHandle(_handle); + _ = Advapi32.CloseServiceHandle(_handle); _handle = IntPtr.Zero; } } @@ -71,7 +71,7 @@ namespace winsw.Native Marshal.StructureToPtr(actions[i], new IntPtr(sfa.lpsaActions.ToInt64() + i * len), false); } - if (!Advapi32.ChangeServiceConfig2(Handle, SERVICE_CONFIG_INFOLEVEL.SERVICE_CONFIG_FAILURE_ACTIONS, ref sfa)) + if (!Advapi32.ChangeServiceConfig2(Handle, SERVICE_CONFIG_INFOLEVEL.SERVICE_CONFIG_FAILURE_ACTIONS, sfa)) throw new Exception("Failed to change the failure actions", new Win32Exception()); } finally @@ -94,7 +94,7 @@ namespace winsw.Native fDelayedAutostart = enabled }; - if (!Advapi32.ChangeServiceConfig2(Handle, SERVICE_CONFIG_INFOLEVEL.SERVICE_CONFIG_DELAYED_AUTO_START_INFO, ref settings)) + if (!Advapi32.ChangeServiceConfig2(Handle, SERVICE_CONFIG_INFOLEVEL.SERVICE_CONFIG_DELAYED_AUTO_START_INFO, settings)) { throw new Exception("Failed to change the DelayedAutoStart setting", new Win32Exception()); } @@ -103,7 +103,7 @@ namespace winsw.Native public void Dispose() { if (Handle != IntPtr.Zero) - Advapi32.CloseServiceHandle(Handle); + _ = Advapi32.CloseServiceHandle(Handle); Handle = IntPtr.Zero; } } @@ -174,19 +174,16 @@ namespace winsw.Native // StringBuilder and size for the domain name StringBuilder domainName = new StringBuilder(); int nameSize = 0; - // account-type variable for lookup - int accountType = 0; // get required buffer size - Advapi32.LookupAccountName(string.Empty, accountName, sid, ref sidSize, domainName, ref nameSize, ref accountType); + _ = Advapi32.LookupAccountName(null, accountName, sid, ref sidSize, domainName, ref nameSize, out _); // allocate buffers domainName = new StringBuilder(nameSize); sid = Marshal.AllocHGlobal(sidSize); // lookup the SID for the account - bool result = Advapi32.LookupAccountName(string.Empty, accountName, sid, ref sidSize, domainName, ref nameSize, - ref accountType); + bool result = Advapi32.LookupAccountName(null, accountName, sid, ref sidSize, domainName, ref nameSize, out _); // say what you're doing // Console.WriteLine("LookupAccountName result = " + result); @@ -200,8 +197,6 @@ namespace winsw.Native } else { - // initialize an empty unicode-string - LSA_UNICODE_STRING systemName = default; // combine all policies const int access = (int)( LSA_AccessPolicy.POLICY_AUDIT_LOG_ADMIN | @@ -220,18 +215,8 @@ namespace winsw.Native ); // initialize a pointer for the policy handle - // these attributes are not used, but LsaOpenPolicy wants them to exists - LSA_OBJECT_ATTRIBUTES objectAttributes = new LSA_OBJECT_ATTRIBUTES - { - Length = 0, - RootDirectory = IntPtr.Zero, - Attributes = 0, - SecurityDescriptor = IntPtr.Zero, - SecurityQualityOfService = IntPtr.Zero - }; - // get a policy handle - uint resultPolicy = Advapi32.LsaOpenPolicy(ref systemName, ref objectAttributes, access, out IntPtr policyHandle); + uint resultPolicy = Advapi32.LsaOpenPolicy(default, default, access, out IntPtr policyHandle); winErrorCode = Advapi32.LsaNtStatusToWinError(resultPolicy); if (winErrorCode != 0) @@ -257,7 +242,7 @@ namespace winsw.Native Console.WriteLine("LsaAddAccountRights failed: " + winErrorCode); } - Advapi32.LsaClose(policyHandle); + _ = Advapi32.LsaClose(policyHandle); } Advapi32.FreeSid(sid); @@ -276,16 +261,13 @@ namespace winsw.Native private const string Advapi32LibraryName = "advapi32.dll"; [DllImport(Advapi32LibraryName, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "ChangeServiceConfig2W")] - internal static extern bool ChangeServiceConfig2(IntPtr hService, SERVICE_CONFIG_INFOLEVEL dwInfoLevel, IntPtr lpInfo); + internal static extern bool ChangeServiceConfig2(IntPtr hService, SERVICE_CONFIG_INFOLEVEL dwInfoLevel, in SERVICE_FAILURE_ACTIONS lpInfo); [DllImport(Advapi32LibraryName, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "ChangeServiceConfig2W")] - internal static extern bool ChangeServiceConfig2(IntPtr hService, SERVICE_CONFIG_INFOLEVEL dwInfoLevel, ref SERVICE_FAILURE_ACTIONS sfa); - - [DllImport(Advapi32LibraryName, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "ChangeServiceConfig2W")] - internal static extern bool ChangeServiceConfig2(IntPtr hService, SERVICE_CONFIG_INFOLEVEL dwInfoLevel, ref SERVICE_DELAYED_AUTO_START sfa); + internal static extern bool ChangeServiceConfig2(IntPtr hService, SERVICE_CONFIG_INFOLEVEL dwInfoLevel, in SERVICE_DELAYED_AUTO_START lpInfo); [DllImport(Advapi32LibraryName, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "OpenSCManagerW")] - internal static extern IntPtr OpenSCManager(string? machineName, string? databaseName, uint dwAccess); + internal static extern IntPtr OpenSCManager(string? lpMachineName, string? lpDatabaseName, uint dwDesiredAccess); [DllImport(Advapi32LibraryName, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "OpenServiceW")] internal static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess); @@ -294,10 +276,13 @@ namespace winsw.Native internal static extern bool CloseServiceHandle(IntPtr hSCObject); [DllImport(Advapi32LibraryName)] - public static extern bool SetServiceStatus(IntPtr hServiceStatus, ref SERVICE_STATUS lpServiceStatus); + public static extern bool SetServiceStatus(IntPtr hServiceStatus, in SERVICE_STATUS lpServiceStatus); [DllImport(Advapi32LibraryName)] - internal static extern uint LsaOpenPolicy(ref LSA_UNICODE_STRING SystemName, ref LSA_OBJECT_ATTRIBUTES ObjectAttributes, int DesiredAccess, + internal static extern uint LsaOpenPolicy( + in LSA_UNICODE_STRING SystemName, + in LSA_OBJECT_ATTRIBUTES ObjectAttributes, + int DesiredAccess, out IntPtr PolicyHandle); [DllImport(Advapi32LibraryName, SetLastError = true)] @@ -307,8 +292,14 @@ namespace winsw.Native internal static extern void FreeSid(IntPtr pSid); [DllImport(Advapi32LibraryName, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "LookupAccountNameW")] - internal static extern bool LookupAccountName(string lpSystemName, string lpAccountName, IntPtr psid, ref int cbsid, StringBuilder domainName, - ref int cbdomainLength, ref int use); + internal static extern bool LookupAccountName( + string? lpSystemName, + string lpAccountName, + IntPtr psid, + ref int cbsid, + StringBuilder domainName, + ref int cbdomainLength, + out int use); [DllImport(Advapi32LibraryName)] internal static extern bool IsValidSid(IntPtr pSid); diff --git a/src/Core/WinSWCore/Native/Kernel32.cs b/src/Core/WinSWCore/Native/Kernel32.cs index 73d29b9..32528c1 100755 --- a/src/Core/WinSWCore/Native/Kernel32.cs +++ b/src/Core/WinSWCore/Native/Kernel32.cs @@ -9,6 +9,8 @@ namespace winsw.Native /// public class Kernel32 { + public const uint CREATE_NEW_PROCESS_GROUP = 0x00000200; + private const string Kernel32LibraryName = "kernel32.dll"; [DllImport(Kernel32LibraryName, SetLastError = true)] @@ -17,14 +19,14 @@ namespace winsw.Native [DllImport(Kernel32LibraryName, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "CreateProcessW")] public static extern bool CreateProcess( string? lpApplicationName, - string lpCommandLine, + string? lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string? lpCurrentDirectory, - [In] ref STARTUPINFO lpStartupInfo, + in STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation); } diff --git a/src/Core/WinSWCore/Util/SigIntHelper.cs b/src/Core/WinSWCore/Util/SigIntHelper.cs index c915d19..b8ede86 100644 --- a/src/Core/WinSWCore/Util/SigIntHelper.cs +++ b/src/Core/WinSWCore/Util/SigIntHelper.cs @@ -47,8 +47,8 @@ namespace winsw.Util if (AttachConsole((uint)process.Id)) { // Disable Ctrl-C handling for our program - SetConsoleCtrlHandler(null, true); - GenerateConsoleCtrlEvent(CtrlTypes.CTRL_C_EVENT, 0); + _ = SetConsoleCtrlHandler(null, true); + _ = GenerateConsoleCtrlEvent(CtrlTypes.CTRL_C_EVENT, 0); process.WaitForExit((int)shutdownTimeout.TotalMilliseconds); From 3a70a9ef3e2632539f7fedef7738e1c8e5a46f0f Mon Sep 17 00:00:00 2001 From: Oleg Nenashev Date: Tue, 24 Mar 2020 16:53:20 +0100 Subject: [PATCH 08/13] Update the repository location in README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 374d3dd..51ae722 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ winsw: Windows service wrapper in less restrictive license ========================= -[![Github All Releases](https://img.shields.io/github/downloads/kohsuke/winsw/total.svg)](https://github.com/kohsuke/winsw/releases) +[![Github All Releases](https://img.shields.io/github/downloads/winsw/winsw/total.svg)](https://github.com/winsw/winsw/releases) [![NuGet](https://img.shields.io/nuget/v/WinSW.svg)](https://www.nuget.org/packages/WinSW/) [![Build status](https://ci.appveyor.com/api/projects/status/i94752yal9iy77in?svg=true)](https://ci.appveyor.com/project/oleg-nenashev/winsw) @@ -14,7 +14,7 @@ See the [project manifest](MANIFEST.md). ### Download -Starting from WinSW `2.x`, the releases are being hosted on [GitHub](https://github.com/kohsuke/winsw/releases) and [nuget.org](https://www.nuget.org/packages/WinSW/). +Starting from WinSW `2.x`, the releases are being hosted on [GitHub](https://github.com/winsw/winsw/releases) and [nuget.org](https://www.nuget.org/packages/WinSW/). Due to historical reasons, the project also uses [Jenkins Maven repository](https://jenkins.io/index.html) as a secondary source. Binaries are available [here](http://repo.jenkins-ci.org/releases/com/sun/winsw/winsw/). From cee902e8c39beb9b1ed43bbf624d7d50f329bc89 Mon Sep 17 00:00:00 2001 From: Oleg Nenashev Date: Tue, 24 Mar 2020 16:59:48 +0100 Subject: [PATCH 09/13] Update WinSW hyperlink in the archived changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7631025..256fc0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ Release Notes ##### Newer releases -See [GitHub Releases](https://github.com/kohsuke/winsw/releases) +See [GitHub Releases](https://github.com/winsw/winsw/releases) ##### 2.3.0 From 8f5a8612826a4c45a142a7823813a25e1e1fc9d8 Mon Sep 17 00:00:00 2001 From: Oleg Nenashev Date: Tue, 24 Mar 2020 17:22:24 +0100 Subject: [PATCH 10/13] Update the repo reference in the NuGet spec --- WinSW.nuspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WinSW.nuspec b/WinSW.nuspec index 466b887..4889596 100644 --- a/WinSW.nuspec +++ b/WinSW.nuspec @@ -15,7 +15,7 @@ More info about the wrapper is available in the projects GitHub repository. WinSW contributors Oleg Nenashev, Kohsuke Kawaguchi MIT - https://github.com/kohsuke/winsw + https://github.com/winsw/winsw Copyright (c) 2010-2016 Kohsuke Kawaguchi, Sun Microsystems, Inc., CloudBees, Inc., Oleg Nenashev and other contributors false From 8e1e1e8704c7c400e9c66153ad97ec608eb27ea2 Mon Sep 17 00:00:00 2001 From: Oleg Nenashev Date: Tue, 24 Mar 2020 18:19:33 +0100 Subject: [PATCH 11/13] Add a Gitter chat for the project --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 374d3dd..6cc4bf4 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ winsw: Windows service wrapper in less restrictive license [![Github All Releases](https://img.shields.io/github/downloads/kohsuke/winsw/total.svg)](https://github.com/kohsuke/winsw/releases) [![NuGet](https://img.shields.io/nuget/v/WinSW.svg)](https://www.nuget.org/packages/WinSW/) [![Build status](https://ci.appveyor.com/api/projects/status/i94752yal9iy77in?svg=true)](https://ci.appveyor.com/project/oleg-nenashev/winsw) +[![Gitter](https://badges.gitter.im/winsw/winsw.svg)](https://gitter.im/winsw/winsw?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) WinSW is an executable binary, which can be used to wrap and manage a custom process as a Windows service. Once you download the installation package, you can rename `winsw.exe` to any name, e.g. `myService.exe`. From 60840fadecf3d2629b7bba8426dbf820f320aef8 Mon Sep 17 00:00:00 2001 From: Oleg Nenashev Date: Wed, 25 Mar 2020 10:43:36 +0100 Subject: [PATCH 12/13] Update CODEOWNERS to request reviews from all maintainers (#451) * Update CODEOWNERS to request reviews from all maintainers * mention maintainers explicitly --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 9bda637..eb4c561 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @oleg-nenashev +* @oleg-nenashev @NextTurn From 634fc0a54197d5ce20e3f44879f211ee973b0cdc Mon Sep 17 00:00:00 2001 From: Oleg Nenashev Date: Wed, 25 Mar 2020 10:52:56 +0100 Subject: [PATCH 13/13] Add .NET 4.6.1 package to the NuGet specification --- WinSW.nuspec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/WinSW.nuspec b/WinSW.nuspec index 466b887..5814405 100644 --- a/WinSW.nuspec +++ b/WinSW.nuspec @@ -27,7 +27,9 @@ More info about the wrapper is available in the projects GitHub repository. + +