diff --git a/Greenshot/Forms/AboutForm.Designer.cs b/Greenshot/Forms/AboutForm.Designer.cs
index 1b35f8699..a2ff0904b 100644
--- a/Greenshot/Forms/AboutForm.Designer.cs
+++ b/Greenshot/Forms/AboutForm.Designer.cs
@@ -21,6 +21,7 @@
using System.Windows.Forms;
using Greenshot.Helpers;
+using GreenshotPlugin.Core;
namespace Greenshot.Forms {
partial class AboutForm {
diff --git a/GreenshotImgurPlugin/ImgurUtils.cs b/GreenshotImgurPlugin/ImgurUtils.cs
index 9b1e73e68..580b89c66 100644
--- a/GreenshotImgurPlugin/ImgurUtils.cs
+++ b/GreenshotImgurPlugin/ImgurUtils.cs
@@ -169,11 +169,11 @@ namespace GreenshotImgurPlugin {
{
AuthUrlPattern = "https://api.imgur.com/oauth2/authorize?response_type=token&client_id={ClientId}&state={State}",
TokenUrl = "https://api.imgur.com/oauth2/token",
- RedirectUrl = "https://getgreenshot.org/oauth/imgur",
+ RedirectUrl = "https://getgreenshot.org/authorize/imgur",
CloudServiceName = "Imgur",
ClientId = ImgurCredentials.CONSUMER_KEY,
ClientSecret = ImgurCredentials.CONSUMER_SECRET,
- AuthorizeMode = OAuth2AuthorizeMode.MonitorTitle,
+ AuthorizeMode = OAuth2AuthorizeMode.JsonReceiver,
RefreshToken = Config.RefreshToken,
AccessToken = Config.AccessToken,
AccessTokenExpires = Config.AccessTokenExpires
diff --git a/Greenshot/Helpers/EnvironmentInfo.cs b/GreenshotPlugin/Core/EnvironmentInfo.cs
similarity index 96%
rename from Greenshot/Helpers/EnvironmentInfo.cs
rename to GreenshotPlugin/Core/EnvironmentInfo.cs
index 59caf857e..ba0c061d2 100644
--- a/Greenshot/Helpers/EnvironmentInfo.cs
+++ b/GreenshotPlugin/Core/EnvironmentInfo.cs
@@ -1,855 +1,854 @@
-/*
- * Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom
- *
- * For more information see: http://getgreenshot.org/
- * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-using System;
-using System.Reflection;
-using System.Runtime.InteropServices;
-using System.Text;
-using GreenshotPlugin.Core;
-using GreenshotPlugin.IniFile;
-using GreenshotPlugin.UnmanagedHelpers;
-using Microsoft.Win32;
-
-namespace Greenshot.Helpers
-{
- ///
- /// Description of EnvironmentInfo.
- ///
- public static class EnvironmentInfo
- {
- private static bool? _isWindows;
-
- public static bool IsWindows
- {
- get
- {
- if (_isWindows.HasValue)
- {
- return _isWindows.Value;
- }
- _isWindows = Environment.OSVersion.Platform.ToString().StartsWith("Win");
- return _isWindows.Value;
- }
- }
-
- public static bool IsNet45OrNewer()
- {
- // Class "ReflectionContext" exists from .NET 4.5 onwards.
- return Type.GetType("System.Reflection.ReflectionContext", false) != null;
- }
-
- public static string GetGreenshotVersion(bool shortVersion = false)
- {
- var executingAssembly = Assembly.GetExecutingAssembly();
-
- // Use assembly version
- string greenshotVersion = executingAssembly.GetName().Version.ToString();
-
- // Use AssemblyFileVersion if available
- var assemblyFileVersionAttribute = executingAssembly.GetCustomAttribute();
- if (!string.IsNullOrEmpty(assemblyFileVersionAttribute?.Version))
- {
- var assemblyFileVersion = new Version(assemblyFileVersionAttribute.Version);
- greenshotVersion = assemblyFileVersion.ToString(3);
- }
-
- if (!shortVersion)
- {
- // Use AssemblyInformationalVersion if available
- var informationalVersionAttribute = executingAssembly.GetCustomAttribute();
- if (!string.IsNullOrEmpty(informationalVersionAttribute?.InformationalVersion))
- {
- greenshotVersion = informationalVersionAttribute.InformationalVersion;
- }
- }
-
- return greenshotVersion.Replace("+", " - ");
- }
-
- public static string EnvironmentToString(bool newline)
- {
- StringBuilder environment = new StringBuilder();
- environment.Append("Software version: " + GetGreenshotVersion());
- if (IniConfig.IsPortable) {
- environment.Append(" Portable");
- }
- environment.Append(" (" + OsInfo.Bits + " bit)");
-
- if (newline)
- {
- environment.AppendLine();
- }
- else
- {
- environment.Append(", ");
- }
- environment.Append(".NET runtime version: " + Environment.Version);
- if (IsNet45OrNewer())
- {
- environment.Append("+");
-
- }
- if (newline)
- {
- environment.AppendLine();
- }
- else
- {
- environment.Append(", ");
- }
- environment.Append("Time: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss zzz"));
-
- if (IsWindows)
- {
- if (newline)
- {
- environment.AppendLine();
- }
- else
- {
- environment.Append(", ");
- }
-
- environment.Append($"OS: {OsInfo.Name}");
- if (!string.IsNullOrEmpty(OsInfo.Edition))
- {
- environment.Append($" {OsInfo.Edition}");
-
- }
- if (!string.IsNullOrEmpty(OsInfo.ServicePack))
- {
- environment.Append($" {OsInfo.ServicePack}");
-
- }
- environment.Append($" x{OsInfo.Bits}");
- environment.Append($" {OsInfo.VersionString}");
- if (newline)
- {
- environment.AppendLine();
- }
- else
- {
- environment.Append(", ");
- }
- // Get some important information for fixing GDI related Problems
- environment.AppendFormat("GDI object count: {0}", User32.GetGuiResourcesGDICount());
- if (newline)
- {
- environment.AppendLine();
- }
- else
- {
- environment.Append(", ");
- }
- environment.AppendFormat("User object count: {0}", User32.GetGuiResourcesUserCount());
- }
- else
- {
- if (newline)
- {
- environment.AppendLine();
- }
- else
- {
- environment.Append(", ");
- }
- environment.AppendFormat("OS: {0}", Environment.OSVersion.Platform);
- }
- if (newline)
- {
- environment.AppendLine();
- }
- else
- {
- environment.Append(", ");
- }
- // TODO: Is this needed?
- // environment.AppendFormat("Surface count: {0}", Surface.Count);
-
- return environment.ToString();
- }
-
- public static string ExceptionToString(Exception ex)
- {
- if (ex == null)
- return "null\r\n";
-
- StringBuilder report = new StringBuilder();
-
- report.AppendLine("Exception: " + ex.GetType());
- report.AppendLine("Message: " + ex.Message);
- if (ex.Data.Count > 0)
- {
- report.AppendLine();
- report.AppendLine("Additional Information:");
- foreach (object key in ex.Data.Keys)
- {
- object data = ex.Data[key];
- if (data != null)
- {
- report.AppendLine(key + " : " + data);
- }
- }
- }
- if (ex is ExternalException)
- {
- // e.g. COMException
- report.AppendLine().AppendLine("ErrorCode: 0x" + (ex as ExternalException).ErrorCode.ToString("X"));
- }
-
- report.AppendLine().AppendLine("Stack:").AppendLine(ex.StackTrace);
-
- if (ex is ReflectionTypeLoadException)
- {
- report.AppendLine().AppendLine("LoaderExceptions: ");
- foreach (Exception cbE in (ex as ReflectionTypeLoadException).LoaderExceptions)
- {
- report.AppendLine(cbE.Message);
- }
- }
-
- if (ex.InnerException != null)
- {
- report.AppendLine("--- InnerException: ---");
- report.AppendLine(ExceptionToString(ex.InnerException));
- }
- return report.ToString();
- }
-
- public static string BuildReport(Exception exception)
- {
- StringBuilder exceptionText = new StringBuilder();
- exceptionText.AppendLine(EnvironmentToString(true));
- exceptionText.AppendLine(ExceptionToString(exception));
- exceptionText.AppendLine("Configuration dump:");
-
- return exceptionText.ToString();
- }
- }
-
- ///
- /// Provides detailed information about the host operating system.
- /// Code is available at: http://www.csharp411.com/determine-windows-version-and-edition-with-c/
- ///
- public static class OsInfo
- {
- ///
- /// Determines if the current application is 32 or 64-bit.
- ///
- public static int Bits => IntPtr.Size * 8;
-
- private static string _sEdition;
-
- ///
- /// Gets the edition of the operating system running on this computer.
- ///
- public static string Edition
- {
- get
- {
- if (_sEdition != null)
- {
- return _sEdition; //***** RETURN *****//
- }
-
- string edition = string.Empty;
-
- OperatingSystem osVersion = Environment.OSVersion;
- OSVERSIONINFOEX osVersionInfo = OSVERSIONINFOEX.Create();
-
- if (GetVersionEx(ref osVersionInfo))
- {
- int majorVersion = osVersion.Version.Major;
- int minorVersion = osVersion.Version.Minor;
- byte productType = osVersionInfo.ProductType;
- ushort suiteMask = osVersionInfo.SuiteMask;
-
- if (majorVersion == 4)
- {
- if (productType == VER_NT_WORKSTATION)
- {
- // Windows NT 4.0 Workstation
- edition = "Workstation";
- }
- else if (productType == VER_NT_SERVER)
- {
- edition = (suiteMask & VER_SUITE_ENTERPRISE) != 0 ? "Enterprise Server" : "Standard Server";
- }
- }
-
- else if (majorVersion == 5)
- {
- if (productType == VER_NT_WORKSTATION)
- {
- if ((suiteMask & VER_SUITE_PERSONAL) != 0)
- {
- // Windows XP Home Edition
- edition = "Home";
- }
- else
- {
- // Windows XP / Windows 2000 Professional
- edition = "Professional";
- }
- }
- else if (productType == VER_NT_SERVER)
- {
- if (minorVersion == 0)
- {
- if ((suiteMask & VER_SUITE_DATACENTER) != 0)
- {
- // Windows 2000 Datacenter Server
- edition = "Datacenter Server";
- }
- else if ((suiteMask & VER_SUITE_ENTERPRISE) != 0)
- {
- // Windows 2000 Advanced Server
- edition = "Advanced Server";
- }
- else
- {
- // Windows 2000 Server
- edition = "Server";
- }
- }
- else
- {
- if ((suiteMask & VER_SUITE_DATACENTER) != 0)
- {
- // Windows Server 2003 Datacenter Edition
- edition = "Datacenter";
- }
- else if ((suiteMask & VER_SUITE_ENTERPRISE) != 0)
- {
- // Windows Server 2003 Enterprise Edition
- edition = "Enterprise";
- }
- else if ((suiteMask & VER_SUITE_BLADE) != 0)
- {
- // Windows Server 2003 Web Edition
- edition = "Web Edition";
- }
- else
- {
- // Windows Server 2003 Standard Edition
- edition = "Standard";
- }
- }
- }
- }
-
- else if (majorVersion == 6)
- {
- if (GetProductInfo(majorVersion, minorVersion, osVersionInfo.ServicePackMajor, osVersionInfo.ServicePackMinor, out var ed))
- {
- switch (ed)
- {
- case PRODUCT_BUSINESS:
- edition = "Business";
- break;
- case PRODUCT_BUSINESS_N:
- edition = "Business N";
- break;
- case PRODUCT_CLUSTER_SERVER:
- edition = "HPC Edition";
- break;
- case PRODUCT_DATACENTER_SERVER:
- edition = "Datacenter Server";
- break;
- case PRODUCT_DATACENTER_SERVER_CORE:
- edition = "Datacenter Server (core installation)";
- break;
- case PRODUCT_ENTERPRISE:
- edition = "Enterprise";
- break;
- case PRODUCT_ENTERPRISE_N:
- edition = "Enterprise N";
- break;
- case PRODUCT_ENTERPRISE_SERVER:
- edition = "Enterprise Server";
- break;
- case PRODUCT_ENTERPRISE_SERVER_CORE:
- edition = "Enterprise Server (core installation)";
- break;
- case PRODUCT_ENTERPRISE_SERVER_CORE_V:
- edition = "Enterprise Server without Hyper-V (core installation)";
- break;
- case PRODUCT_ENTERPRISE_SERVER_IA64:
- edition = "Enterprise Server for Itanium-based Systems";
- break;
- case PRODUCT_ENTERPRISE_SERVER_V:
- edition = "Enterprise Server without Hyper-V";
- break;
- case PRODUCT_HOME_BASIC:
- edition = "Home Basic";
- break;
- case PRODUCT_HOME_BASIC_N:
- edition = "Home Basic N";
- break;
- case PRODUCT_HOME_PREMIUM:
- edition = "Home Premium";
- break;
- case PRODUCT_HOME_PREMIUM_N:
- edition = "Home Premium N";
- break;
- case PRODUCT_HYPERV:
- edition = "Microsoft Hyper-V Server";
- break;
- case PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT:
- edition = "Windows Essential Business Management Server";
- break;
- case PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING:
- edition = "Windows Essential Business Messaging Server";
- break;
- case PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY:
- edition = "Windows Essential Business Security Server";
- break;
- case PRODUCT_SERVER_FOR_SMALLBUSINESS:
- edition = "Windows Essential Server Solutions";
- break;
- case PRODUCT_SERVER_FOR_SMALLBUSINESS_V:
- edition = "Windows Essential Server Solutions without Hyper-V";
- break;
- case PRODUCT_SMALLBUSINESS_SERVER:
- edition = "Windows Small Business Server";
- break;
- case PRODUCT_STANDARD_SERVER:
- edition = "Standard Server";
- break;
- case PRODUCT_STANDARD_SERVER_CORE:
- edition = "Standard Server (core installation)";
- break;
- case PRODUCT_STANDARD_SERVER_CORE_V:
- edition = "Standard Server without Hyper-V (core installation)";
- break;
- case PRODUCT_STANDARD_SERVER_V:
- edition = "Standard Server without Hyper-V";
- break;
- case PRODUCT_STARTER:
- edition = "Starter";
- break;
- case PRODUCT_STORAGE_ENTERPRISE_SERVER:
- edition = "Enterprise Storage Server";
- break;
- case PRODUCT_STORAGE_EXPRESS_SERVER:
- edition = "Express Storage Server";
- break;
- case PRODUCT_STORAGE_STANDARD_SERVER:
- edition = "Standard Storage Server";
- break;
- case PRODUCT_STORAGE_WORKGROUP_SERVER:
- edition = "Workgroup Storage Server";
- break;
- case PRODUCT_UNDEFINED:
- edition = "Unknown product";
- break;
- case PRODUCT_ULTIMATE:
- edition = "Ultimate";
- break;
- case PRODUCT_ULTIMATE_N:
- edition = "Ultimate N";
- break;
- case PRODUCT_WEB_SERVER:
- edition = "Web Server";
- break;
- case PRODUCT_WEB_SERVER_CORE:
- edition = "Web Server (core installation)";
- break;
- }
- }
- }
- }
-
- _sEdition = edition;
- return edition;
- }
- }
-
- private static string _name;
- ///
- /// Gets the name of the operating system running on this computer.
- ///
- public static string Name
- {
- get
- {
- if (_name != null)
- {
- return _name; //***** RETURN *****//
- }
-
- string name = "unknown";
-
- OperatingSystem osVersion = Environment.OSVersion;
- OSVERSIONINFOEX osVersionInfo = OSVERSIONINFOEX.Create();
- if (GetVersionEx(ref osVersionInfo))
- {
- int majorVersion = osVersion.Version.Major;
- int minorVersion = osVersion.Version.Minor;
- byte productType = osVersionInfo.ProductType;
- ushort suiteMask = osVersionInfo.SuiteMask;
- switch (osVersion.Platform)
- {
- case PlatformID.Win32Windows:
- if (majorVersion == 4)
- {
- string csdVersion = osVersionInfo.ServicePackVersion;
- switch (minorVersion)
- {
- case 0:
- if (csdVersion == "B" || csdVersion == "C")
- {
- name = "Windows 95 OSR2";
- }
- else
- {
- name = "Windows 95";
- }
- break;
- case 10:
- name = csdVersion == "A" ? "Windows 98 Second Edition" : "Windows 98";
- break;
- case 90:
- name = "Windows Me";
- break;
- }
- }
- break;
- case PlatformID.Win32NT:
- switch (majorVersion)
- {
- case 3:
- name = "Windows NT 3.51";
- break;
- case 4:
- switch (productType)
- {
- case 1:
- name = "Windows NT 4.0";
- break;
- case 3:
- name = "Windows NT 4.0 Server";
- break;
- }
- break;
- case 5:
- switch (minorVersion)
- {
- case 0:
- name = "Windows 2000";
- break;
- case 1:
- name = suiteMask switch
- {
- 0x0200 => "Windows XP Professional",
- _ => "Windows XP"
- };
- break;
- case 2:
- name = suiteMask switch
- {
- 0x0200 => "Windows XP Professional x64",
- 0x0002 => "Windows Server 2003 Enterprise",
- 0x0080 => "Windows Server 2003 Data Center",
- 0x0400 => "Windows Server 2003 Web Edition",
- 0x8000 => "Windows Home Server",
- _ => "Windows Server 2003"
- };
- break;
- }
- break;
- case 6:
- switch (minorVersion)
- {
- case 0:
- name = productType switch
- {
- 3 => "Windows Server 2008",
- _ => "Windows Vista"
- };
- break;
- case 1:
- name = productType switch
- {
- 3 => "Windows Server 2008 R2",
- _ => "Windows 7"
- };
- break;
- case 2:
- name = "Windows 8";
- break;
- case 3:
- name = "Windows 8.1";
- break;
- }
- break;
- case 10:
- string releaseId = Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "ReleaseId", "").ToString();
- name = $"Windows 10 {releaseId}";
- break;
- }
- break;
- }
- }
-
- _name = name;
- return name;
- }
- }
-
- [DllImport("Kernel32.dll")]
- [return: MarshalAs(UnmanagedType.Bool)]
- internal static extern bool GetProductInfo(
- int osMajorVersion,
- int osMinorVersion,
- int spMajorVersion,
- int spMinorVersion,
- out int edition);
-
- [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
- [return: MarshalAs(UnmanagedType.Bool)]
- private static extern bool GetVersionEx(ref OSVERSIONINFOEX osVersionInfo);
-
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- private unsafe struct OSVERSIONINFOEX
- {
- ///
- /// The size of this data structure, in bytes. Set this member to sizeof(OSVERSIONINFOEX).
- ///
- private int _dwOSVersionInfoSize;
-
- private readonly int _dwMajorVersion;
- private readonly int _dwMinorVersion;
- private readonly int _dwBuildNumber;
- private readonly int _dwPlatformId;
- private fixed char _szCSDVersion[128];
- private readonly short _wServicePackMajor;
- private readonly short _wServicePackMinor;
- private readonly ushort _wSuiteMask;
- private readonly byte _wProductType;
- private readonly byte _wReserved;
-
- ///
- /// The major version number of the operating system.
- ///
- public int MajorVersion => _dwMajorVersion;
-
- ///
- /// The minor version number of the operating system.
- ///
- public int MinorVersion => _dwMinorVersion;
-
- ///
- /// The build number of the operating system.
- ///
- public int BuildNumber => _dwBuildNumber;
-
- ///
- /// The operating system platform. This member can be VER_PLATFORM_WIN32_NT (2).
- ///
- public int PlatformId => _dwPlatformId;
-
- ///
- /// A null-terminated string, such as "Service Pack 3", that indicates the latest Service Pack installed on the system.
- /// If no Service Pack has been installed, the string is empty.
- ///
- public string ServicePackVersion
- {
- get
- {
- fixed (char* servicePackVersion = _szCSDVersion)
- {
- return new string(servicePackVersion);
- }
-
- }
- }
-
- ///
- /// The major version number of the latest Service Pack installed on the system. For example, for Service Pack 3, the
- /// major version number is 3.
- /// If no Service Pack has been installed, the value is zero.
- ///
- public short ServicePackMajor => _wServicePackMajor;
-
- ///
- /// The minor version number of the latest Service Pack installed on the system. For example, for Service Pack 3, the
- /// minor version number is 0.
- ///
- public short ServicePackMinor => _wServicePackMinor;
-
- ///
- /// A bit mask that identifies the product suites available on the system. This member can be a combination of the
- /// following values.
- ///
- public ushort SuiteMask => _wSuiteMask;
-
- ///
- /// Any additional information about the system.
- ///
- public byte ProductType => _wProductType;
-
- ///
- /// Factory for an empty OsVersionInfoEx
- ///
- /// OSVERSIONINFOEX
- public static OSVERSIONINFOEX Create()
- {
- return new OSVERSIONINFOEX
- {
- _dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEX))
- };
- }
- }
-
- private const int PRODUCT_UNDEFINED = 0x00000000;
- private const int PRODUCT_ULTIMATE = 0x00000001;
- private const int PRODUCT_HOME_BASIC = 0x00000002;
- private const int PRODUCT_HOME_PREMIUM = 0x00000003;
- private const int PRODUCT_ENTERPRISE = 0x00000004;
- private const int PRODUCT_HOME_BASIC_N = 0x00000005;
- private const int PRODUCT_BUSINESS = 0x00000006;
- private const int PRODUCT_STANDARD_SERVER = 0x00000007;
- private const int PRODUCT_DATACENTER_SERVER = 0x00000008;
- private const int PRODUCT_SMALLBUSINESS_SERVER = 0x00000009;
- private const int PRODUCT_ENTERPRISE_SERVER = 0x0000000A;
- private const int PRODUCT_STARTER = 0x0000000B;
- private const int PRODUCT_DATACENTER_SERVER_CORE = 0x0000000C;
- private const int PRODUCT_STANDARD_SERVER_CORE = 0x0000000D;
- private const int PRODUCT_ENTERPRISE_SERVER_CORE = 0x0000000E;
- private const int PRODUCT_ENTERPRISE_SERVER_IA64 = 0x0000000F;
- private const int PRODUCT_BUSINESS_N = 0x00000010;
- private const int PRODUCT_WEB_SERVER = 0x00000011;
- private const int PRODUCT_CLUSTER_SERVER = 0x00000012;
- private const int PRODUCT_STORAGE_EXPRESS_SERVER = 0x00000014;
- private const int PRODUCT_STORAGE_STANDARD_SERVER = 0x00000015;
- private const int PRODUCT_STORAGE_WORKGROUP_SERVER = 0x00000016;
- private const int PRODUCT_STORAGE_ENTERPRISE_SERVER = 0x00000017;
- private const int PRODUCT_SERVER_FOR_SMALLBUSINESS = 0x00000018;
- private const int PRODUCT_HOME_PREMIUM_N = 0x0000001A;
- private const int PRODUCT_ENTERPRISE_N = 0x0000001B;
- private const int PRODUCT_ULTIMATE_N = 0x0000001C;
- private const int PRODUCT_WEB_SERVER_CORE = 0x0000001D;
- private const int PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT = 0x0000001E;
- private const int PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY = 0x0000001F;
- private const int PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING = 0x00000020;
- private const int PRODUCT_SERVER_FOR_SMALLBUSINESS_V = 0x00000023;
- private const int PRODUCT_STANDARD_SERVER_V = 0x00000024;
- private const int PRODUCT_ENTERPRISE_SERVER_V = 0x00000026;
- private const int PRODUCT_STANDARD_SERVER_CORE_V = 0x00000028;
- private const int PRODUCT_ENTERPRISE_SERVER_CORE_V = 0x00000029;
- private const int PRODUCT_HYPERV = 0x0000002A;
-
- private const int VER_NT_WORKSTATION = 1;
- private const int VER_NT_SERVER = 3;
- private const int VER_SUITE_ENTERPRISE = 2;
- private const int VER_SUITE_DATACENTER = 128;
- private const int VER_SUITE_PERSONAL = 512;
- private const int VER_SUITE_BLADE = 1024;
-
- ///
- /// Gets the service pack information of the operating system running on this computer.
- ///
- public static string ServicePack
- {
- get
- {
- string servicePack = string.Empty;
- OSVERSIONINFOEX osVersionInfo = OSVERSIONINFOEX.Create();
-
- if (GetVersionEx(ref osVersionInfo))
- {
- servicePack = osVersionInfo.ServicePackVersion;
- }
-
- return servicePack;
- }
- }
-
- ///
- /// Gets the build version number of the operating system running on this computer.
- ///
- public static int BuildVersion => Environment.OSVersion.Version.Build;
-
- ///
- /// Gets the full version string of the operating system running on this computer.
- ///
- public static string VersionString
- {
- get
- {
- if (WindowsVersion.IsWindows10OrLater)
- {
- return $"build {Environment.OSVersion.Version.Build}";
- }
- if (Environment.OSVersion.Version.Revision != 0)
- {
- return $"{Environment.OSVersion.Version.Major}.{Environment.OSVersion.Version.Minor} build {Environment.OSVersion.Version.Build} revision {Environment.OSVersion.Version.Revision:X}";
- }
- return $"{Environment.OSVersion.Version.Major}.{Environment.OSVersion.Version.Minor} build {Environment.OSVersion.Version.Build}";
- }
- }
-
- ///
- /// Gets the full version of the operating system running on this computer.
- ///
- public static Version Version
- {
- get
- {
- return Environment.OSVersion.Version;
- }
- }
-
- ///
- /// Gets the major version number of the operating system running on this computer.
- ///
- public static int MajorVersion
- {
- get
- {
- return Environment.OSVersion.Version.Major;
- }
- }
-
- ///
- /// Gets the minor version number of the operating system running on this computer.
- ///
- public static int MinorVersion
- {
- get
- {
- return Environment.OSVersion.Version.Minor;
- }
- }
-
- ///
- /// Gets the revision version number of the operating system running on this computer.
- ///
- public static int RevisionVersion
- {
- get
- {
- return Environment.OSVersion.Version.Revision;
- }
- }
- }
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using GreenshotPlugin.IniFile;
+using GreenshotPlugin.UnmanagedHelpers;
+using Microsoft.Win32;
+
+namespace GreenshotPlugin.Core
+{
+ ///
+ /// Description of EnvironmentInfo.
+ ///
+ public static class EnvironmentInfo
+ {
+ private static bool? _isWindows;
+
+ public static bool IsWindows
+ {
+ get
+ {
+ if (_isWindows.HasValue)
+ {
+ return _isWindows.Value;
+ }
+ _isWindows = Environment.OSVersion.Platform.ToString().StartsWith("Win");
+ return _isWindows.Value;
+ }
+ }
+
+ public static bool IsNet45OrNewer()
+ {
+ // Class "ReflectionContext" exists from .NET 4.5 onwards.
+ return Type.GetType("System.Reflection.ReflectionContext", false) != null;
+ }
+
+ public static string GetGreenshotVersion(bool shortVersion = false)
+ {
+ var executingAssembly = Assembly.GetExecutingAssembly();
+
+ // Use assembly version
+ string greenshotVersion = executingAssembly.GetName().Version.ToString();
+
+ // Use AssemblyFileVersion if available
+ var assemblyFileVersionAttribute = executingAssembly.GetCustomAttribute();
+ if (!string.IsNullOrEmpty(assemblyFileVersionAttribute?.Version))
+ {
+ var assemblyFileVersion = new Version(assemblyFileVersionAttribute.Version);
+ greenshotVersion = assemblyFileVersion.ToString(3);
+ }
+
+ if (!shortVersion)
+ {
+ // Use AssemblyInformationalVersion if available
+ var informationalVersionAttribute = executingAssembly.GetCustomAttribute();
+ if (!string.IsNullOrEmpty(informationalVersionAttribute?.InformationalVersion))
+ {
+ greenshotVersion = informationalVersionAttribute.InformationalVersion;
+ }
+ }
+
+ return greenshotVersion.Replace("+", " - ");
+ }
+
+ public static string EnvironmentToString(bool newline)
+ {
+ StringBuilder environment = new StringBuilder();
+ environment.Append("Software version: " + GetGreenshotVersion());
+ if (IniConfig.IsPortable) {
+ environment.Append(" Portable");
+ }
+ environment.Append(" (" + OsInfo.Bits + " bit)");
+
+ if (newline)
+ {
+ environment.AppendLine();
+ }
+ else
+ {
+ environment.Append(", ");
+ }
+ environment.Append(".NET runtime version: " + Environment.Version);
+ if (IsNet45OrNewer())
+ {
+ environment.Append("+");
+
+ }
+ if (newline)
+ {
+ environment.AppendLine();
+ }
+ else
+ {
+ environment.Append(", ");
+ }
+ environment.Append("Time: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss zzz"));
+
+ if (IsWindows)
+ {
+ if (newline)
+ {
+ environment.AppendLine();
+ }
+ else
+ {
+ environment.Append(", ");
+ }
+
+ environment.Append($"OS: {OsInfo.Name}");
+ if (!string.IsNullOrEmpty(OsInfo.Edition))
+ {
+ environment.Append($" {OsInfo.Edition}");
+
+ }
+ if (!string.IsNullOrEmpty(OsInfo.ServicePack))
+ {
+ environment.Append($" {OsInfo.ServicePack}");
+
+ }
+ environment.Append($" x{OsInfo.Bits}");
+ environment.Append($" {OsInfo.VersionString}");
+ if (newline)
+ {
+ environment.AppendLine();
+ }
+ else
+ {
+ environment.Append(", ");
+ }
+ // Get some important information for fixing GDI related Problems
+ environment.AppendFormat("GDI object count: {0}", User32.GetGuiResourcesGDICount());
+ if (newline)
+ {
+ environment.AppendLine();
+ }
+ else
+ {
+ environment.Append(", ");
+ }
+ environment.AppendFormat("User object count: {0}", User32.GetGuiResourcesUserCount());
+ }
+ else
+ {
+ if (newline)
+ {
+ environment.AppendLine();
+ }
+ else
+ {
+ environment.Append(", ");
+ }
+ environment.AppendFormat("OS: {0}", Environment.OSVersion.Platform);
+ }
+ if (newline)
+ {
+ environment.AppendLine();
+ }
+ else
+ {
+ environment.Append(", ");
+ }
+ // TODO: Is this needed?
+ // environment.AppendFormat("Surface count: {0}", Surface.Count);
+
+ return environment.ToString();
+ }
+
+ public static string ExceptionToString(Exception ex)
+ {
+ if (ex == null)
+ return "null\r\n";
+
+ StringBuilder report = new StringBuilder();
+
+ report.AppendLine("Exception: " + ex.GetType());
+ report.AppendLine("Message: " + ex.Message);
+ if (ex.Data.Count > 0)
+ {
+ report.AppendLine();
+ report.AppendLine("Additional Information:");
+ foreach (object key in ex.Data.Keys)
+ {
+ object data = ex.Data[key];
+ if (data != null)
+ {
+ report.AppendLine(key + " : " + data);
+ }
+ }
+ }
+ if (ex is ExternalException)
+ {
+ // e.g. COMException
+ report.AppendLine().AppendLine("ErrorCode: 0x" + (ex as ExternalException).ErrorCode.ToString("X"));
+ }
+
+ report.AppendLine().AppendLine("Stack:").AppendLine(ex.StackTrace);
+
+ if (ex is ReflectionTypeLoadException)
+ {
+ report.AppendLine().AppendLine("LoaderExceptions: ");
+ foreach (Exception cbE in (ex as ReflectionTypeLoadException).LoaderExceptions)
+ {
+ report.AppendLine(cbE.Message);
+ }
+ }
+
+ if (ex.InnerException != null)
+ {
+ report.AppendLine("--- InnerException: ---");
+ report.AppendLine(ExceptionToString(ex.InnerException));
+ }
+ return report.ToString();
+ }
+
+ public static string BuildReport(Exception exception)
+ {
+ StringBuilder exceptionText = new StringBuilder();
+ exceptionText.AppendLine(EnvironmentToString(true));
+ exceptionText.AppendLine(ExceptionToString(exception));
+ exceptionText.AppendLine("Configuration dump:");
+
+ return exceptionText.ToString();
+ }
+ }
+
+ ///
+ /// Provides detailed information about the host operating system.
+ /// Code is available at: http://www.csharp411.com/determine-windows-version-and-edition-with-c/
+ ///
+ public static class OsInfo
+ {
+ ///
+ /// Determines if the current application is 32 or 64-bit.
+ ///
+ public static int Bits => IntPtr.Size * 8;
+
+ private static string _sEdition;
+
+ ///
+ /// Gets the edition of the operating system running on this computer.
+ ///
+ public static string Edition
+ {
+ get
+ {
+ if (_sEdition != null)
+ {
+ return _sEdition; //***** RETURN *****//
+ }
+
+ string edition = string.Empty;
+
+ OperatingSystem osVersion = Environment.OSVersion;
+ OSVERSIONINFOEX osVersionInfo = OSVERSIONINFOEX.Create();
+
+ if (GetVersionEx(ref osVersionInfo))
+ {
+ int majorVersion = osVersion.Version.Major;
+ int minorVersion = osVersion.Version.Minor;
+ byte productType = osVersionInfo.ProductType;
+ ushort suiteMask = osVersionInfo.SuiteMask;
+
+ if (majorVersion == 4)
+ {
+ if (productType == VER_NT_WORKSTATION)
+ {
+ // Windows NT 4.0 Workstation
+ edition = "Workstation";
+ }
+ else if (productType == VER_NT_SERVER)
+ {
+ edition = (suiteMask & VER_SUITE_ENTERPRISE) != 0 ? "Enterprise Server" : "Standard Server";
+ }
+ }
+
+ else if (majorVersion == 5)
+ {
+ if (productType == VER_NT_WORKSTATION)
+ {
+ if ((suiteMask & VER_SUITE_PERSONAL) != 0)
+ {
+ // Windows XP Home Edition
+ edition = "Home";
+ }
+ else
+ {
+ // Windows XP / Windows 2000 Professional
+ edition = "Professional";
+ }
+ }
+ else if (productType == VER_NT_SERVER)
+ {
+ if (minorVersion == 0)
+ {
+ if ((suiteMask & VER_SUITE_DATACENTER) != 0)
+ {
+ // Windows 2000 Datacenter Server
+ edition = "Datacenter Server";
+ }
+ else if ((suiteMask & VER_SUITE_ENTERPRISE) != 0)
+ {
+ // Windows 2000 Advanced Server
+ edition = "Advanced Server";
+ }
+ else
+ {
+ // Windows 2000 Server
+ edition = "Server";
+ }
+ }
+ else
+ {
+ if ((suiteMask & VER_SUITE_DATACENTER) != 0)
+ {
+ // Windows Server 2003 Datacenter Edition
+ edition = "Datacenter";
+ }
+ else if ((suiteMask & VER_SUITE_ENTERPRISE) != 0)
+ {
+ // Windows Server 2003 Enterprise Edition
+ edition = "Enterprise";
+ }
+ else if ((suiteMask & VER_SUITE_BLADE) != 0)
+ {
+ // Windows Server 2003 Web Edition
+ edition = "Web Edition";
+ }
+ else
+ {
+ // Windows Server 2003 Standard Edition
+ edition = "Standard";
+ }
+ }
+ }
+ }
+
+ else if (majorVersion == 6)
+ {
+ if (GetProductInfo(majorVersion, minorVersion, osVersionInfo.ServicePackMajor, osVersionInfo.ServicePackMinor, out var ed))
+ {
+ switch (ed)
+ {
+ case PRODUCT_BUSINESS:
+ edition = "Business";
+ break;
+ case PRODUCT_BUSINESS_N:
+ edition = "Business N";
+ break;
+ case PRODUCT_CLUSTER_SERVER:
+ edition = "HPC Edition";
+ break;
+ case PRODUCT_DATACENTER_SERVER:
+ edition = "Datacenter Server";
+ break;
+ case PRODUCT_DATACENTER_SERVER_CORE:
+ edition = "Datacenter Server (core installation)";
+ break;
+ case PRODUCT_ENTERPRISE:
+ edition = "Enterprise";
+ break;
+ case PRODUCT_ENTERPRISE_N:
+ edition = "Enterprise N";
+ break;
+ case PRODUCT_ENTERPRISE_SERVER:
+ edition = "Enterprise Server";
+ break;
+ case PRODUCT_ENTERPRISE_SERVER_CORE:
+ edition = "Enterprise Server (core installation)";
+ break;
+ case PRODUCT_ENTERPRISE_SERVER_CORE_V:
+ edition = "Enterprise Server without Hyper-V (core installation)";
+ break;
+ case PRODUCT_ENTERPRISE_SERVER_IA64:
+ edition = "Enterprise Server for Itanium-based Systems";
+ break;
+ case PRODUCT_ENTERPRISE_SERVER_V:
+ edition = "Enterprise Server without Hyper-V";
+ break;
+ case PRODUCT_HOME_BASIC:
+ edition = "Home Basic";
+ break;
+ case PRODUCT_HOME_BASIC_N:
+ edition = "Home Basic N";
+ break;
+ case PRODUCT_HOME_PREMIUM:
+ edition = "Home Premium";
+ break;
+ case PRODUCT_HOME_PREMIUM_N:
+ edition = "Home Premium N";
+ break;
+ case PRODUCT_HYPERV:
+ edition = "Microsoft Hyper-V Server";
+ break;
+ case PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT:
+ edition = "Windows Essential Business Management Server";
+ break;
+ case PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING:
+ edition = "Windows Essential Business Messaging Server";
+ break;
+ case PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY:
+ edition = "Windows Essential Business Security Server";
+ break;
+ case PRODUCT_SERVER_FOR_SMALLBUSINESS:
+ edition = "Windows Essential Server Solutions";
+ break;
+ case PRODUCT_SERVER_FOR_SMALLBUSINESS_V:
+ edition = "Windows Essential Server Solutions without Hyper-V";
+ break;
+ case PRODUCT_SMALLBUSINESS_SERVER:
+ edition = "Windows Small Business Server";
+ break;
+ case PRODUCT_STANDARD_SERVER:
+ edition = "Standard Server";
+ break;
+ case PRODUCT_STANDARD_SERVER_CORE:
+ edition = "Standard Server (core installation)";
+ break;
+ case PRODUCT_STANDARD_SERVER_CORE_V:
+ edition = "Standard Server without Hyper-V (core installation)";
+ break;
+ case PRODUCT_STANDARD_SERVER_V:
+ edition = "Standard Server without Hyper-V";
+ break;
+ case PRODUCT_STARTER:
+ edition = "Starter";
+ break;
+ case PRODUCT_STORAGE_ENTERPRISE_SERVER:
+ edition = "Enterprise Storage Server";
+ break;
+ case PRODUCT_STORAGE_EXPRESS_SERVER:
+ edition = "Express Storage Server";
+ break;
+ case PRODUCT_STORAGE_STANDARD_SERVER:
+ edition = "Standard Storage Server";
+ break;
+ case PRODUCT_STORAGE_WORKGROUP_SERVER:
+ edition = "Workgroup Storage Server";
+ break;
+ case PRODUCT_UNDEFINED:
+ edition = "Unknown product";
+ break;
+ case PRODUCT_ULTIMATE:
+ edition = "Ultimate";
+ break;
+ case PRODUCT_ULTIMATE_N:
+ edition = "Ultimate N";
+ break;
+ case PRODUCT_WEB_SERVER:
+ edition = "Web Server";
+ break;
+ case PRODUCT_WEB_SERVER_CORE:
+ edition = "Web Server (core installation)";
+ break;
+ }
+ }
+ }
+ }
+
+ _sEdition = edition;
+ return edition;
+ }
+ }
+
+ private static string _name;
+ ///
+ /// Gets the name of the operating system running on this computer.
+ ///
+ public static string Name
+ {
+ get
+ {
+ if (_name != null)
+ {
+ return _name; //***** RETURN *****//
+ }
+
+ string name = "unknown";
+
+ OperatingSystem osVersion = Environment.OSVersion;
+ OSVERSIONINFOEX osVersionInfo = OSVERSIONINFOEX.Create();
+ if (GetVersionEx(ref osVersionInfo))
+ {
+ int majorVersion = osVersion.Version.Major;
+ int minorVersion = osVersion.Version.Minor;
+ byte productType = osVersionInfo.ProductType;
+ ushort suiteMask = osVersionInfo.SuiteMask;
+ switch (osVersion.Platform)
+ {
+ case PlatformID.Win32Windows:
+ if (majorVersion == 4)
+ {
+ string csdVersion = osVersionInfo.ServicePackVersion;
+ switch (minorVersion)
+ {
+ case 0:
+ if (csdVersion == "B" || csdVersion == "C")
+ {
+ name = "Windows 95 OSR2";
+ }
+ else
+ {
+ name = "Windows 95";
+ }
+ break;
+ case 10:
+ name = csdVersion == "A" ? "Windows 98 Second Edition" : "Windows 98";
+ break;
+ case 90:
+ name = "Windows Me";
+ break;
+ }
+ }
+ break;
+ case PlatformID.Win32NT:
+ switch (majorVersion)
+ {
+ case 3:
+ name = "Windows NT 3.51";
+ break;
+ case 4:
+ switch (productType)
+ {
+ case 1:
+ name = "Windows NT 4.0";
+ break;
+ case 3:
+ name = "Windows NT 4.0 Server";
+ break;
+ }
+ break;
+ case 5:
+ switch (minorVersion)
+ {
+ case 0:
+ name = "Windows 2000";
+ break;
+ case 1:
+ name = suiteMask switch
+ {
+ 0x0200 => "Windows XP Professional",
+ _ => "Windows XP"
+ };
+ break;
+ case 2:
+ name = suiteMask switch
+ {
+ 0x0200 => "Windows XP Professional x64",
+ 0x0002 => "Windows Server 2003 Enterprise",
+ 0x0080 => "Windows Server 2003 Data Center",
+ 0x0400 => "Windows Server 2003 Web Edition",
+ 0x8000 => "Windows Home Server",
+ _ => "Windows Server 2003"
+ };
+ break;
+ }
+ break;
+ case 6:
+ switch (minorVersion)
+ {
+ case 0:
+ name = productType switch
+ {
+ 3 => "Windows Server 2008",
+ _ => "Windows Vista"
+ };
+ break;
+ case 1:
+ name = productType switch
+ {
+ 3 => "Windows Server 2008 R2",
+ _ => "Windows 7"
+ };
+ break;
+ case 2:
+ name = "Windows 8";
+ break;
+ case 3:
+ name = "Windows 8.1";
+ break;
+ }
+ break;
+ case 10:
+ string releaseId = Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "ReleaseId", "").ToString();
+ name = $"Windows 10 {releaseId}";
+ break;
+ }
+ break;
+ }
+ }
+
+ _name = name;
+ return name;
+ }
+ }
+
+ [DllImport("Kernel32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool GetProductInfo(
+ int osMajorVersion,
+ int osMinorVersion,
+ int spMajorVersion,
+ int spMinorVersion,
+ out int edition);
+
+ [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool GetVersionEx(ref OSVERSIONINFOEX osVersionInfo);
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ private unsafe struct OSVERSIONINFOEX
+ {
+ ///
+ /// The size of this data structure, in bytes. Set this member to sizeof(OSVERSIONINFOEX).
+ ///
+ private int _dwOSVersionInfoSize;
+
+ private readonly int _dwMajorVersion;
+ private readonly int _dwMinorVersion;
+ private readonly int _dwBuildNumber;
+ private readonly int _dwPlatformId;
+ private fixed char _szCSDVersion[128];
+ private readonly short _wServicePackMajor;
+ private readonly short _wServicePackMinor;
+ private readonly ushort _wSuiteMask;
+ private readonly byte _wProductType;
+ private readonly byte _wReserved;
+
+ ///
+ /// The major version number of the operating system.
+ ///
+ public int MajorVersion => _dwMajorVersion;
+
+ ///
+ /// The minor version number of the operating system.
+ ///
+ public int MinorVersion => _dwMinorVersion;
+
+ ///
+ /// The build number of the operating system.
+ ///
+ public int BuildNumber => _dwBuildNumber;
+
+ ///
+ /// The operating system platform. This member can be VER_PLATFORM_WIN32_NT (2).
+ ///
+ public int PlatformId => _dwPlatformId;
+
+ ///
+ /// A null-terminated string, such as "Service Pack 3", that indicates the latest Service Pack installed on the system.
+ /// If no Service Pack has been installed, the string is empty.
+ ///
+ public string ServicePackVersion
+ {
+ get
+ {
+ fixed (char* servicePackVersion = _szCSDVersion)
+ {
+ return new string(servicePackVersion);
+ }
+
+ }
+ }
+
+ ///
+ /// The major version number of the latest Service Pack installed on the system. For example, for Service Pack 3, the
+ /// major version number is 3.
+ /// If no Service Pack has been installed, the value is zero.
+ ///
+ public short ServicePackMajor => _wServicePackMajor;
+
+ ///
+ /// The minor version number of the latest Service Pack installed on the system. For example, for Service Pack 3, the
+ /// minor version number is 0.
+ ///
+ public short ServicePackMinor => _wServicePackMinor;
+
+ ///
+ /// A bit mask that identifies the product suites available on the system. This member can be a combination of the
+ /// following values.
+ ///
+ public ushort SuiteMask => _wSuiteMask;
+
+ ///
+ /// Any additional information about the system.
+ ///
+ public byte ProductType => _wProductType;
+
+ ///
+ /// Factory for an empty OsVersionInfoEx
+ ///
+ /// OSVERSIONINFOEX
+ public static OSVERSIONINFOEX Create()
+ {
+ return new OSVERSIONINFOEX
+ {
+ _dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEX))
+ };
+ }
+ }
+
+ private const int PRODUCT_UNDEFINED = 0x00000000;
+ private const int PRODUCT_ULTIMATE = 0x00000001;
+ private const int PRODUCT_HOME_BASIC = 0x00000002;
+ private const int PRODUCT_HOME_PREMIUM = 0x00000003;
+ private const int PRODUCT_ENTERPRISE = 0x00000004;
+ private const int PRODUCT_HOME_BASIC_N = 0x00000005;
+ private const int PRODUCT_BUSINESS = 0x00000006;
+ private const int PRODUCT_STANDARD_SERVER = 0x00000007;
+ private const int PRODUCT_DATACENTER_SERVER = 0x00000008;
+ private const int PRODUCT_SMALLBUSINESS_SERVER = 0x00000009;
+ private const int PRODUCT_ENTERPRISE_SERVER = 0x0000000A;
+ private const int PRODUCT_STARTER = 0x0000000B;
+ private const int PRODUCT_DATACENTER_SERVER_CORE = 0x0000000C;
+ private const int PRODUCT_STANDARD_SERVER_CORE = 0x0000000D;
+ private const int PRODUCT_ENTERPRISE_SERVER_CORE = 0x0000000E;
+ private const int PRODUCT_ENTERPRISE_SERVER_IA64 = 0x0000000F;
+ private const int PRODUCT_BUSINESS_N = 0x00000010;
+ private const int PRODUCT_WEB_SERVER = 0x00000011;
+ private const int PRODUCT_CLUSTER_SERVER = 0x00000012;
+ private const int PRODUCT_STORAGE_EXPRESS_SERVER = 0x00000014;
+ private const int PRODUCT_STORAGE_STANDARD_SERVER = 0x00000015;
+ private const int PRODUCT_STORAGE_WORKGROUP_SERVER = 0x00000016;
+ private const int PRODUCT_STORAGE_ENTERPRISE_SERVER = 0x00000017;
+ private const int PRODUCT_SERVER_FOR_SMALLBUSINESS = 0x00000018;
+ private const int PRODUCT_HOME_PREMIUM_N = 0x0000001A;
+ private const int PRODUCT_ENTERPRISE_N = 0x0000001B;
+ private const int PRODUCT_ULTIMATE_N = 0x0000001C;
+ private const int PRODUCT_WEB_SERVER_CORE = 0x0000001D;
+ private const int PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT = 0x0000001E;
+ private const int PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY = 0x0000001F;
+ private const int PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING = 0x00000020;
+ private const int PRODUCT_SERVER_FOR_SMALLBUSINESS_V = 0x00000023;
+ private const int PRODUCT_STANDARD_SERVER_V = 0x00000024;
+ private const int PRODUCT_ENTERPRISE_SERVER_V = 0x00000026;
+ private const int PRODUCT_STANDARD_SERVER_CORE_V = 0x00000028;
+ private const int PRODUCT_ENTERPRISE_SERVER_CORE_V = 0x00000029;
+ private const int PRODUCT_HYPERV = 0x0000002A;
+
+ private const int VER_NT_WORKSTATION = 1;
+ private const int VER_NT_SERVER = 3;
+ private const int VER_SUITE_ENTERPRISE = 2;
+ private const int VER_SUITE_DATACENTER = 128;
+ private const int VER_SUITE_PERSONAL = 512;
+ private const int VER_SUITE_BLADE = 1024;
+
+ ///
+ /// Gets the service pack information of the operating system running on this computer.
+ ///
+ public static string ServicePack
+ {
+ get
+ {
+ string servicePack = string.Empty;
+ OSVERSIONINFOEX osVersionInfo = OSVERSIONINFOEX.Create();
+
+ if (GetVersionEx(ref osVersionInfo))
+ {
+ servicePack = osVersionInfo.ServicePackVersion;
+ }
+
+ return servicePack;
+ }
+ }
+
+ ///
+ /// Gets the build version number of the operating system running on this computer.
+ ///
+ public static int BuildVersion => Environment.OSVersion.Version.Build;
+
+ ///
+ /// Gets the full version string of the operating system running on this computer.
+ ///
+ public static string VersionString
+ {
+ get
+ {
+ if (WindowsVersion.IsWindows10OrLater)
+ {
+ return $"build {Environment.OSVersion.Version.Build}";
+ }
+ if (Environment.OSVersion.Version.Revision != 0)
+ {
+ return $"{Environment.OSVersion.Version.Major}.{Environment.OSVersion.Version.Minor} build {Environment.OSVersion.Version.Build} revision {Environment.OSVersion.Version.Revision:X}";
+ }
+ return $"{Environment.OSVersion.Version.Major}.{Environment.OSVersion.Version.Minor} build {Environment.OSVersion.Version.Build}";
+ }
+ }
+
+ ///
+ /// Gets the full version of the operating system running on this computer.
+ ///
+ public static Version Version
+ {
+ get
+ {
+ return Environment.OSVersion.Version;
+ }
+ }
+
+ ///
+ /// Gets the major version number of the operating system running on this computer.
+ ///
+ public static int MajorVersion
+ {
+ get
+ {
+ return Environment.OSVersion.Version.Major;
+ }
+ }
+
+ ///
+ /// Gets the minor version number of the operating system running on this computer.
+ ///
+ public static int MinorVersion
+ {
+ get
+ {
+ return Environment.OSVersion.Version.Minor;
+ }
+ }
+
+ ///
+ /// Gets the revision version number of the operating system running on this computer.
+ ///
+ public static int RevisionVersion
+ {
+ get
+ {
+ return Environment.OSVersion.Version.Revision;
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/GreenshotPlugin/Core/OAuth/LocalJsonReceiver.cs b/GreenshotPlugin/Core/OAuth/LocalJsonReceiver.cs
new file mode 100644
index 000000000..7b363b2fa
--- /dev/null
+++ b/GreenshotPlugin/Core/OAuth/LocalJsonReceiver.cs
@@ -0,0 +1,191 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using System.Threading;
+using log4net;
+using Newtonsoft.Json;
+
+namespace GreenshotPlugin.Core.OAuth
+{
+ ///
+ /// OAuth 2.0 verification code receiver that runs a local server on a free port
+ /// and waits for a call with the authorization verification code.
+ ///
+ public class LocalJsonReceiver
+ {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(LocalJsonReceiver));
+ private readonly ManualResetEvent _ready = new ManualResetEvent(true);
+ private IDictionary _returnValues;
+
+ ///
+ /// The url format for the website to post to. Expects one port parameter.
+ /// Default: http://localhost:{0}/authorize/
+ ///
+ public string ListeningUrlFormat { get; set; } = "http://localhost:{0}/authorize/";
+
+ private string _listeningUri;
+ ///
+ /// The URL where the server is listening
+ ///
+ public string ListeningUri {
+ get {
+ if (string.IsNullOrEmpty(_listeningUri))
+ {
+ _listeningUri = string.Format(ListeningUrlFormat, GetRandomUnusedPort());
+ }
+ return _listeningUri;
+ }
+ set => _listeningUri = value;
+ }
+
+ ///
+ /// This action is called when the URI must be opened, default is just to run Process.Start
+ ///
+ public Action OpenUriAction
+ {
+ set;
+ get;
+ } = authorizationUrl =>
+ {
+ Log.DebugFormat("Open a browser with: {0}", authorizationUrl);
+ using var process = Process.Start(authorizationUrl);
+ };
+
+ ///
+ /// Timeout for waiting for the website to respond
+ ///
+ public TimeSpan Timeout { get; set; } = TimeSpan.FromMinutes(4);
+
+ ///
+ /// The OAuth code receiver
+ ///
+ /// OAuth2Settings
+ /// Dictionary with values
+ public IDictionary ReceiveCode(OAuth2Settings oauth2Settings) {
+ using var listener = new HttpListener();
+ // Make sure the port is stored in the state, so the website can process this.
+ oauth2Settings.State = new Uri(ListeningUri).Port.ToString();
+ listener.Prefixes.Add(ListeningUri);
+ try {
+ listener.Start();
+ _ready.Reset();
+
+ listener.BeginGetContext(ListenerCallback, listener);
+ OpenUriAction(oauth2Settings.FormattedAuthUrl);
+ _ready.WaitOne(Timeout, true);
+ } catch (Exception) {
+ // Make sure we can clean up, also if the thead is aborted
+ _ready.Set();
+ throw;
+ } finally {
+ listener.Close();
+ }
+
+ return _returnValues;
+ }
+
+ ///
+ /// Handle a connection async, this allows us to break the waiting
+ ///
+ /// IAsyncResult
+ private void ListenerCallback(IAsyncResult result) {
+ HttpListener listener = (HttpListener)result.AsyncState;
+
+ //If not listening return immediately as this method is called one last time after Close()
+ if (!listener.IsListening) {
+ return;
+ }
+
+ // Use EndGetContext to complete the asynchronous operation.
+ HttpListenerContext context = listener.EndGetContext(result);
+
+ // Handle request
+ HttpListenerRequest request = context.Request;
+
+ if (request.HasEntityBody)
+ {
+ // Process the body
+ using var body = request.InputStream;
+ using var reader = new StreamReader(body, request.ContentEncoding);
+ using var jsonTextReader = new JsonTextReader(reader);
+ var serializer = new JsonSerializer();
+ _returnValues = serializer.Deserialize>(jsonTextReader);
+ }
+
+ // Create the response.
+ using (HttpListenerResponse response = context.Response)
+ {
+ if (request.HttpMethod == "OPTIONS")
+ {
+ response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With");
+ response.AddHeader("Access-Control-Allow-Methods", "POST");
+ response.AddHeader("Access-Control-Max-Age", "1728000");
+ }
+
+ response.AppendHeader("Access-Control-Allow-Origin", "*");
+ if (request.HasEntityBody)
+ {
+ response.ContentType = "application/json";
+ // currently only return the version, more can be added later
+ string jsonContent = "{\"version\": \"" + EnvironmentInfo.GetGreenshotVersion(true) + "\"}";
+
+ // Write a "close" response.
+ byte[] buffer = Encoding.UTF8.GetBytes(jsonContent);
+ // Write to response stream.
+ response.ContentLength64 = buffer.Length;
+ using var stream = response.OutputStream;
+ stream.Write(buffer, 0, buffer.Length);
+ }
+ }
+
+ if (_returnValues != null)
+ {
+ _ready.Set();
+ }
+ else
+ {
+ // Make sure the next request is processed
+ listener.BeginGetContext(ListenerCallback, listener);
+ }
+ }
+
+ ///
+ /// Returns a random, unused port.
+ ///
+ /// port to use
+ private static int GetRandomUnusedPort() {
+ var listener = new TcpListener(IPAddress.Loopback, 0);
+ try {
+ listener.Start();
+ return ((IPEndPoint)listener.LocalEndpoint).Port;
+ } finally {
+ listener.Stop();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/GreenshotPlugin/Core/OAuth/OAuth2AuthorizeMode.cs b/GreenshotPlugin/Core/OAuth/OAuth2AuthorizeMode.cs
index b5eee19b3..98d4515f9 100644
--- a/GreenshotPlugin/Core/OAuth/OAuth2AuthorizeMode.cs
+++ b/GreenshotPlugin/Core/OAuth/OAuth2AuthorizeMode.cs
@@ -27,8 +27,7 @@ namespace GreenshotPlugin.Core.OAuth
public enum OAuth2AuthorizeMode {
Unknown, // Will give an exception, caller needs to specify another value
LocalServer, // Will specify a redirect URL to http://localhost:port/authorize, while having a HttpListener
- MonitorTitle, // Will monitor for title changes, the title needs the status and query params
- Pin, // Not implemented yet: Will ask the user to enter the shown PIN
+ JsonReceiver, // Will start a local HttpListener and wait for a Json post
EmbeddedBrowser // Will open into an embedded _browser (OAuthLoginForm), and catch the redirect
}
}
\ No newline at end of file
diff --git a/GreenshotPlugin/Core/OAuth/OAuth2Helper.cs b/GreenshotPlugin/Core/OAuth/OAuth2Helper.cs
index 629a764f8..2189f09a1 100644
--- a/GreenshotPlugin/Core/OAuth/OAuth2Helper.cs
+++ b/GreenshotPlugin/Core/OAuth/OAuth2Helper.cs
@@ -21,12 +21,9 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics;
using System.Drawing;
using System.Net;
-using System.Windows.Forms;
using GreenshotPlugin.Controls;
-using GreenshotPlugin.Hooking;
namespace GreenshotPlugin.Core.OAuth {
///
@@ -134,7 +131,7 @@ namespace GreenshotPlugin.Core.OAuth {
///
/// Go out and retrieve a new access token via refresh-token with the TokenUrl in the settings
- /// Will upate the access token, refresh token, expire date
+ /// Will update the access token, refresh token, expire date
///
///
public static void GenerateAccessToken(OAuth2Settings settings) {
@@ -159,22 +156,23 @@ namespace GreenshotPlugin.Core.OAuth {
// "token_type":"Bearer",
IDictionary accessTokenResult = JSONHelper.JsonDecode(accessTokenJsonResult);
- if (accessTokenResult.ContainsKey("error")) {
- if ("invalid_grant" == (string)accessTokenResult["error"]) {
+ if (accessTokenResult.ContainsKey("error"))
+ {
+ if ("invalid_grant" == (string)accessTokenResult["error"]) {
// Refresh token has also expired, we need a new one!
settings.RefreshToken = null;
settings.AccessToken = null;
settings.AccessTokenExpires = DateTimeOffset.MinValue;
settings.Code = null;
return;
- } else {
- if (accessTokenResult.ContainsKey("error_description")) {
- throw new Exception($"{accessTokenResult["error"]} - {accessTokenResult["error_description"]}");
- } else {
- throw new Exception((string)accessTokenResult["error"]);
- }
}
- }
+
+ if (accessTokenResult.ContainsKey("error_description")) {
+ throw new Exception($"{accessTokenResult["error"]} - {accessTokenResult["error_description"]}");
+ }
+
+ throw new Exception((string)accessTokenResult["error"]);
+ }
if (accessTokenResult.ContainsKey(AccessToken))
{
@@ -205,76 +203,62 @@ namespace GreenshotPlugin.Core.OAuth {
{
OAuth2AuthorizeMode.LocalServer => AuthenticateViaLocalServer(settings),
OAuth2AuthorizeMode.EmbeddedBrowser => AuthenticateViaEmbeddedBrowser(settings),
- OAuth2AuthorizeMode.MonitorTitle => AuthenticateViaDefaultBrowser(settings),
+ OAuth2AuthorizeMode.JsonReceiver => AuthenticateViaDefaultBrowser(settings),
_ => throw new NotImplementedException($"Authorize mode '{settings.AuthorizeMode}' is not 'yet' implemented."),
};
return completed;
}
///
- /// Authenticate via the default browser, using the browser title.
+ /// Authenticate via the default browser, via the Greenshot website.
+ /// It will wait for a Json post.
/// If this works, return the code
///
/// OAuth2Settings with the Auth / Token url etc
/// true if completed, false if canceled
private static bool AuthenticateViaDefaultBrowser(OAuth2Settings settings)
{
- var monitor = new WindowsTitleMonitor();
+ var codeReceiver = new LocalJsonReceiver();
+ IDictionary result = codeReceiver.ReceiveCode(settings);
- string error = null;
- var fields = new HashSet();
- int nrOfFields = 100;
-
- monitor.TitleChangeEvent += args =>
+ foreach (var key in result.Keys)
{
- if (!args.Title.Contains(settings.State))
+ switch (key)
{
- return;
+ case AccessToken:
+ settings.AccessToken = result[key];
+ break;
+ case ExpiresIn:
+ if (int.TryParse(result[key], out var seconds))
+ {
+ settings.AccessTokenExpires = DateTimeOffset.Now.AddSeconds(seconds);
+ }
+ break;
+ case RefreshToken:
+ settings.RefreshToken = result[key];
+ break;
}
+ }
- var title = args.Title;
- title = title.Substring(0,title.IndexOf(' '));
-
- var parameters = NetworkHelper.ParseQueryString(title);
-
- if (parameters.ContainsKey("nr"))
+ if (result.TryGetValue("error", out var error))
+ {
+ if (result.TryGetValue("error_description", out var errorDescription))
{
- nrOfFields = int.Parse(parameters["nr"]);
+ throw new Exception(errorDescription);
}
+ if ("access_denied" == error)
+ {
+ throw new UnauthorizedAccessException("Access denied");
+ }
+ throw new Exception(error);
+ }
+ if (result.TryGetValue(Code, out var code) && !string.IsNullOrEmpty(code))
+ {
+ settings.Code = code;
+ GenerateRefreshToken(settings);
+ }
- foreach (var key in parameters.Keys)
- {
- fields.Add(key);
- switch (key)
- {
- case AccessToken:
- settings.AccessToken = parameters[key];
- break;
- case ExpiresIn:
- if (int.TryParse(parameters[key], out var seconds))
- {
- settings.AccessTokenExpires = DateTimeOffset.Now.AddSeconds(seconds);
- }
- break;
- case RefreshToken:
- settings.RefreshToken = parameters[key];
- break;
- case Error:
- error = parameters[key];
- break;
- }
- }
- };
- using (var process = Process.Start(settings.FormattedAuthUrl))
- {
- while (nrOfFields > fields.Count)
- {
- // Have the thread process Forms events
- Application.DoEvents();
- }
- };
- monitor.Dispose();
- return error == null;
+ return true;
}
///