From 85df04e5506a1f7ee439af984af319c3a8f2b96e Mon Sep 17 00:00:00 2001 From: Hugh Bellamy Date: Sun, 6 Oct 2019 10:29:11 +0100 Subject: [PATCH 1/2] Cleanup PowerStatus interop --- src/Common/src/ExternDll.cs | 1 - src/Common/src/Interop/Interop.Libraries.cs | 1 + .../Kernel32/Interop.GetSystemPowerStatus.cs | 14 ++++++++++++++ .../Kernel32/Interop.SYSTEM_POWER_STATUS.cs | 19 +++++++++++++++++++ .../Interop/Powrprof/Interop.GetTickCount.cs | 14 ++++++++++++++ src/Common/src/NativeMethods.cs | 11 ----------- src/Common/src/UnsafeNativeMethods.cs | 8 -------- .../src/Misc/ExternDll.cs | 1 - .../src/System/Windows/Forms/Application.cs | 2 +- .../src/System/Windows/Forms/PowerStatus.cs | 9 ++++----- 10 files changed, 53 insertions(+), 27 deletions(-) create mode 100644 src/Common/src/Interop/Kernel32/Interop.GetSystemPowerStatus.cs create mode 100644 src/Common/src/Interop/Kernel32/Interop.SYSTEM_POWER_STATUS.cs create mode 100644 src/Common/src/Interop/Powrprof/Interop.GetTickCount.cs diff --git a/src/Common/src/ExternDll.cs b/src/Common/src/ExternDll.cs index b3b2191b1ba..1ef27f6b4a9 100644 --- a/src/Common/src/ExternDll.cs +++ b/src/Common/src/ExternDll.cs @@ -26,7 +26,6 @@ internal static class ExternDll public const string Oleaut32 = "oleaut32.dll"; public const string Olepro32 = "olepro32.dll"; public const string PerfCounter = "perfcounter.dll"; - public const string Powrprof = "Powrprof.dll"; public const string Psapi = "psapi.dll"; public const string Shell32 = "shell32.dll"; public const string User32 = "user32.dll"; diff --git a/src/Common/src/Interop/Interop.Libraries.cs b/src/Common/src/Interop/Interop.Libraries.cs index ba29b7e858b..6feccaa0e42 100644 --- a/src/Common/src/Interop/Interop.Libraries.cs +++ b/src/Common/src/Interop/Interop.Libraries.cs @@ -13,6 +13,7 @@ public static partial class Libraries public const string NtDll = "ntdll.dll"; public const string Ole32 = "ole32.dll"; public const string Oleaut32 = "oleaut32.dll"; + public const string Powrprof = "Powrprof.dll"; public const string RichEdit41 = "MsftEdit.DLL"; public const string Shell32 = "shell32.dll"; public const string Shlwapi = "shlwapi.dll"; diff --git a/src/Common/src/Interop/Kernel32/Interop.GetSystemPowerStatus.cs b/src/Common/src/Interop/Kernel32/Interop.GetSystemPowerStatus.cs new file mode 100644 index 00000000000..2d859371c65 --- /dev/null +++ b/src/Common/src/Interop/Kernel32/Interop.GetSystemPowerStatus.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class Kernel32 + { + [DllImport(Libraries.Kernel32, ExactSpelling = true)] + public static extern BOOL GetSystemPowerStatus(ref SYSTEM_POWER_STATUS lpSystemPowerStatus); + } +} diff --git a/src/Common/src/Interop/Kernel32/Interop.SYSTEM_POWER_STATUS.cs b/src/Common/src/Interop/Kernel32/Interop.SYSTEM_POWER_STATUS.cs new file mode 100644 index 00000000000..7f483fa73a1 --- /dev/null +++ b/src/Common/src/Interop/Kernel32/Interop.SYSTEM_POWER_STATUS.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +internal partial class Interop +{ + internal partial class Kernel32 + { + public struct SYSTEM_POWER_STATUS + { + public byte ACLineStatus; + public byte BatteryFlag; + public byte BatteryLifePercent; + public byte Reserved1; + public int BatteryLifeTime; + public int BatteryFullLifeTime; + } + } +} diff --git a/src/Common/src/Interop/Powrprof/Interop.GetTickCount.cs b/src/Common/src/Interop/Powrprof/Interop.GetTickCount.cs new file mode 100644 index 00000000000..1eb498b0ab9 --- /dev/null +++ b/src/Common/src/Interop/Powrprof/Interop.GetTickCount.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class Powrprof + { + [DllImport(Libraries.Powrprof, ExactSpelling = true)] + public static extern bool SetSuspendState(bool bHibernate, bool bForce, bool bWakeupEventsDisabled); + } +} diff --git a/src/Common/src/NativeMethods.cs b/src/Common/src/NativeMethods.cs index a2b1e627217..9d5d9b8a9e9 100644 --- a/src/Common/src/NativeMethods.cs +++ b/src/Common/src/NativeMethods.cs @@ -3336,17 +3336,6 @@ internal static string GetLocalPath(string fileName) return uri.LocalPath + uri.Fragment; } - [StructLayout(LayoutKind.Sequential)] - public struct SYSTEM_POWER_STATUS - { - public byte ACLineStatus; - public byte BatteryFlag; - public byte BatteryLifePercent; - public byte Reserved1; - public int BatteryLifeTime; - public int BatteryFullLifeTime; - } - public enum PROCESS_DPI_AWARENESS { PROCESS_DPI_UNINITIALIZED = -1, diff --git a/src/Common/src/UnsafeNativeMethods.cs b/src/Common/src/UnsafeNativeMethods.cs index de5fba2d1c6..c85a579cae6 100644 --- a/src/Common/src/UnsafeNativeMethods.cs +++ b/src/Common/src/UnsafeNativeMethods.cs @@ -622,14 +622,6 @@ public static IntPtr SetWindowLong(HandleRef hWnd, int nIndex, NativeMethods.Wnd [DllImport(ExternDll.User32, ExactSpelling = true, SetLastError = true)] public static extern uint GetDpiForWindow(HandleRef hWnd); - // For system power status - // - [DllImport(ExternDll.Kernel32, ExactSpelling = true, CharSet = CharSet.Auto)] - public static extern bool GetSystemPowerStatus([In, Out] ref NativeMethods.SYSTEM_POWER_STATUS systemPowerStatus); - - [DllImport(ExternDll.Powrprof, ExactSpelling = true, CharSet = CharSet.Auto)] - public static extern bool SetSuspendState(bool hiberate, bool forceCritical, bool disableWakeEvent); - //for RegionData [DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] public static extern int GetRegionData(HandleRef hRgn, int size, IntPtr lpRgnData); diff --git a/src/System.Windows.Forms.Design.Editors/src/Misc/ExternDll.cs b/src/System.Windows.Forms.Design.Editors/src/Misc/ExternDll.cs index 1e7e9bf9571..dfc1724cdad 100644 --- a/src/System.Windows.Forms.Design.Editors/src/Misc/ExternDll.cs +++ b/src/System.Windows.Forms.Design.Editors/src/Misc/ExternDll.cs @@ -55,7 +55,6 @@ internal static class ExternDll public const string Oleaut32 = "oleaut32.dll"; public const string Olepro32 = "olepro32.dll"; public const string PerfCounter = "perfcounter.dll"; - public const string Powrprof = "Powrprof.dll"; public const string Psapi = "psapi.dll"; public const string Shell32 = "shell32.dll"; public const string User32 = "user32.dll"; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Application.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Application.cs index 1a7edbd4ea1..a6785d833ad 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Application.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Application.cs @@ -1241,7 +1241,7 @@ public static void SetCompatibleTextRenderingDefault(bool defaultValue) /// Returns true if the call succeeded, else false. /// public static bool SetSuspendState(PowerState state, bool force, bool disableWakeEvent) - => UnsafeNativeMethods.SetSuspendState(state == PowerState.Hibernate, force, disableWakeEvent); + => Powrprof.SetSuspendState(state == PowerState.Hibernate, force, disableWakeEvent); /// /// Overload version of SetUnhandledExceptionMode that sets the UnhandledExceptionMode diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/PowerStatus.cs b/src/System.Windows.Forms/src/System/Windows/Forms/PowerStatus.cs index 217205d9c47..216fea7515a 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/PowerStatus.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/PowerStatus.cs @@ -2,11 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using static Interop; + namespace System.Windows.Forms { public class PowerStatus { - private NativeMethods.SYSTEM_POWER_STATUS _systemPowerStatus; + private Kernel32.SYSTEM_POWER_STATUS _systemPowerStatus; internal PowerStatus() { @@ -58,9 +60,6 @@ public int BatteryLifeRemaining } } - private void UpdateSystemPowerStatus() - { - UnsafeNativeMethods.GetSystemPowerStatus(ref _systemPowerStatus); - } + private void UpdateSystemPowerStatus() => Kernel32.GetSystemPowerStatus(ref _systemPowerStatus); } } From cd861f323028d6624597ea7e9bc5dae403ed3f32 Mon Sep 17 00:00:00 2001 From: Hugh Bellamy Date: Tue, 8 Oct 2019 11:25:57 +0100 Subject: [PATCH 2/2] Use BOOLEAN instead of bool --- src/Common/src/Interop/Interop.BOOLEAN.cs | 30 +++++++++++++++++++ ...ickCount.cs => Interop.SetSuspendState.cs} | 4 +-- .../src/System/Windows/Forms/Application.cs | 2 +- 3 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 src/Common/src/Interop/Interop.BOOLEAN.cs rename src/Common/src/Interop/Powrprof/{Interop.GetTickCount.cs => Interop.SetSuspendState.cs} (61%) diff --git a/src/Common/src/Interop/Interop.BOOLEAN.cs b/src/Common/src/Interop/Interop.BOOLEAN.cs new file mode 100644 index 00000000000..350fc131796 --- /dev/null +++ b/src/Common/src/Interop/Interop.BOOLEAN.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using static Interop; + +internal partial class Interop +{ + /// + /// Blittable version of Windows BOOLEAN type. It is convenient in situations where + /// manual marshalling is required, or to avoid overhead of regular BOOLEAN marshalling. + /// + /// + /// Some Windows APIs return arbitrary integer values although the return type is defined + /// as BOOL. It is best to never compare BOOLEAN to TRUE. Always use bResult != BOOLEAN.FALSE + /// or bResult == BOOLEAN.FALSE . + /// + internal enum BOOLEAN : byte + { + FALSE = 0, + TRUE = 1, + } +} + +internal static class BooleanExtensions +{ + public static bool IsTrue(this BOOLEAN b) => b != BOOLEAN.FALSE; + public static bool IsFalse(this BOOLEAN b) => b == BOOLEAN.FALSE; + public static BOOLEAN ToBOOLEAN(this bool b) => b ? BOOLEAN.TRUE : BOOLEAN.FALSE; +} diff --git a/src/Common/src/Interop/Powrprof/Interop.GetTickCount.cs b/src/Common/src/Interop/Powrprof/Interop.SetSuspendState.cs similarity index 61% rename from src/Common/src/Interop/Powrprof/Interop.GetTickCount.cs rename to src/Common/src/Interop/Powrprof/Interop.SetSuspendState.cs index 1eb498b0ab9..a6a8d811ed0 100644 --- a/src/Common/src/Interop/Powrprof/Interop.GetTickCount.cs +++ b/src/Common/src/Interop/Powrprof/Interop.SetSuspendState.cs @@ -8,7 +8,7 @@ internal partial class Interop { internal partial class Powrprof { - [DllImport(Libraries.Powrprof, ExactSpelling = true)] - public static extern bool SetSuspendState(bool bHibernate, bool bForce, bool bWakeupEventsDisabled); + [DllImport(Libraries.Powrprof, ExactSpelling = true, SetLastError = true)] + public static extern BOOLEAN SetSuspendState(BOOLEAN bHibernate, BOOLEAN bForce, BOOLEAN bWakeupEventsDisabled); } } diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Application.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Application.cs index a6785d833ad..49918270819 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Application.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Application.cs @@ -1241,7 +1241,7 @@ public static void SetCompatibleTextRenderingDefault(bool defaultValue) /// Returns true if the call succeeded, else false. /// public static bool SetSuspendState(PowerState state, bool force, bool disableWakeEvent) - => Powrprof.SetSuspendState(state == PowerState.Hibernate, force, disableWakeEvent); + => Powrprof.SetSuspendState((state == PowerState.Hibernate).ToBOOLEAN(), force.ToBOOLEAN(), disableWakeEvent.ToBOOLEAN()).IsTrue(); /// /// Overload version of SetUnhandledExceptionMode that sets the UnhandledExceptionMode