diff --git a/Shadowsocks.PAC/PACDaemon.cs b/Shadowsocks.PAC/PACDaemon.cs index 40a7b7dc1..ce0a8b7c3 100644 --- a/Shadowsocks.PAC/PACDaemon.cs +++ b/Shadowsocks.PAC/PACDaemon.cs @@ -16,11 +16,11 @@ public class PACDaemon : IEnableLogger public const string USER_RULE_FILE = "user-rule.txt"; public const string USER_ABP_FILE = "abp.txt"; - FileSystemWatcher PACFileWatcher; - FileSystemWatcher UserRuleFileWatcher; + FileSystemWatcher? PACFileWatcher; + FileSystemWatcher? UserRuleFileWatcher; - public event EventHandler PACFileChanged; - public event EventHandler UserRuleFileChanged; + public event EventHandler? PACFileChanged; + public event EventHandler? UserRuleFileChanged; private PACSettings _PACSettings; private GeositeUpdater _geositeUpdater; diff --git a/Shadowsocks.PAC/PACServer.cs b/Shadowsocks.PAC/PACServer.cs index 79c5b3f73..b77a633eb 100644 --- a/Shadowsocks.PAC/PACServer.cs +++ b/Shadowsocks.PAC/PACServer.cs @@ -124,7 +124,7 @@ public override bool Handle(byte[] firstPacket, int length, Socket socket, objec { if (kv[0] == "Host") { - if (kv[1].Trim() == ((IPEndPoint)socket.LocalEndPoint).ToString()) + if (kv[1].Trim() == (socket.LocalEndPoint as IPEndPoint)?.ToString()) { hostMatch = true; } @@ -164,7 +164,7 @@ public void SendResponse(Socket socket, bool useSocks) { try { - IPEndPoint localEndPoint = (IPEndPoint)socket.LocalEndPoint; + IPEndPoint localEndPoint = socket.LocalEndPoint as IPEndPoint ?? throw new ArgumentException("Invalid socket local endpoint.", nameof(socket)); string proxy = GetPACAddress(localEndPoint, useSocks); diff --git a/Shadowsocks.WPF/Localization/LocalizationProvider.cs b/Shadowsocks.WPF/Localization/LocalizationProvider.cs index 41358fedc..41d7f2bc6 100644 --- a/Shadowsocks.WPF/Localization/LocalizationProvider.cs +++ b/Shadowsocks.WPF/Localization/LocalizationProvider.cs @@ -5,7 +5,7 @@ namespace Shadowsocks.WPF.Localization { public class LocalizationProvider { - private static readonly string CallingAssemblyName = Assembly.GetCallingAssembly().GetName().Name; + private static readonly string CallingAssemblyName = Assembly.GetCallingAssembly().GetName().Name ?? "Shadowsocks.WPF"; public static T GetLocalizedValue(string key) => LocExtension.GetLocalizedValue($"{CallingAssemblyName}:Strings:{key}"); } diff --git a/Shadowsocks.WPF/Services/PortForwarder.cs b/Shadowsocks.WPF/Services/PortForwarder.cs index b8c363c6c..046e369e2 100644 --- a/Shadowsocks.WPF/Services/PortForwarder.cs +++ b/Shadowsocks.WPF/Services/PortForwarder.cs @@ -6,6 +6,7 @@ namespace Shadowsocks.WPF.Services { +#nullable disable public class PortForwarder : StreamService { private readonly int _targetPort; diff --git a/Shadowsocks.WPF/Services/Sip003Plugin.cs b/Shadowsocks.WPF/Services/Sip003Plugin.cs index 2f1369582..c57f61275 100644 --- a/Shadowsocks.WPF/Services/Sip003Plugin.cs +++ b/Shadowsocks.WPF/Services/Sip003Plugin.cs @@ -12,7 +12,7 @@ namespace Shadowsocks.WPF.Services // https://github.com/shadowsocks/shadowsocks-org/wiki/Plugin public sealed class Sip003Plugin : IDisposable { - public IPEndPoint LocalEndPoint { get; private set; } + public IPEndPoint? LocalEndPoint { get; private set; } public int ProcessId => _started ? _pluginProcess.Id : 0; private readonly object _startProcessLock = new object(); @@ -20,7 +20,7 @@ public sealed class Sip003Plugin : IDisposable private bool _started; private bool _disposed; - public static Sip003Plugin CreateIfConfigured(Server server, bool showPluginOutput) + public static Sip003Plugin? CreateIfConfigured(Server server, bool showPluginOutput) { if (server == null) { @@ -119,7 +119,7 @@ public bool StartIfNeeded() return true; } - public string ExpandEnvironmentVariables(string name, StringDictionary environmentVariables = null) + public string ExpandEnvironmentVariables(string name, StringDictionary? environmentVariables = null) { // Expand the environment variables from the new process itself if (environmentVariables != null) diff --git a/Shadowsocks.WPF/Services/SystemProxy/RAS.cs b/Shadowsocks.WPF/Services/SystemProxy/RAS.cs index b60b56e92..50dfb5129 100644 --- a/Shadowsocks.WPF/Services/SystemProxy/RAS.cs +++ b/Shadowsocks.WPF/Services/SystemProxy/RAS.cs @@ -42,7 +42,7 @@ public class RAS // pointer to full path and file name of phone-book file string lpszPhonebook, // buffer to receive phone-book entries - [In, Out] RasEntryName[] lprasentryname, + [In, Out] RasEntryName[]? lprasentryname, // size in bytes of buffer ref int lpcb, // number of entries written to buffer @@ -55,14 +55,14 @@ public static string[] GetAllConnections() int entryNameSize = 0; int lpSize = 0; uint retval = ESuccess; - RasEntryName[] names = null; + RasEntryName[] names = Array.Empty(); entryNameSize = Marshal.SizeOf(typeof(RasEntryName)); // Windows Vista or later: To determine the required buffer size, call RasEnumEntries // with lprasentryname set to NULL. The variable pointed to by lpcb should be set to zero. // The function will return the required buffer size in lpcb and an error code of ERROR_BUFFER_TOO_SMALL. - retval = RasEnumEntries(null, null, null, ref lpSize, out lpNames); + retval = RasEnumEntries("", "", null, ref lpSize, out lpNames); if (retval == EBufferTooSmall) { names = new RasEntryName[lpNames]; @@ -71,7 +71,7 @@ public static string[] GetAllConnections() names[i].dwSize = entryNameSize; } - retval = RasEnumEntries(null, null, names, ref lpSize, out lpNames); + retval = RasEnumEntries("", "", names, ref lpSize, out lpNames); } if (retval == ESuccess) diff --git a/Shadowsocks.WPF/Services/SystemProxy/WinINet.cs b/Shadowsocks.WPF/Services/SystemProxy/WinINet.cs index de90a6f89..2f80e465c 100644 --- a/Shadowsocks.WPF/Services/SystemProxy/WinINet.cs +++ b/Shadowsocks.WPF/Services/SystemProxy/WinINet.cs @@ -136,7 +136,7 @@ static WinINet() { try { - Record(); + initialSetting = Query(); } catch (DllNotFoundException) { @@ -153,9 +153,14 @@ static WinINet() } else { - throw we; + throw; } } + finally + { + if (initialSetting == null) + initialSetting = new(); + } } public static void ProxyGlobal(string server, string bypass) @@ -188,11 +193,6 @@ public static void Direct() Exec(options); } - private static void Record() - { - initialSetting ??= Query(); - } - public static void Restore() { Set(initialSetting); @@ -231,7 +231,7 @@ public static WinINetSetting Query() new InternetPerConnectionOption{dwOption = (int)InternetPerConnectionOptionEnum.AutoConfigUrl}, }; - (IntPtr unmanagedList, int listSize) = PrepareOptionList(options, null); + (IntPtr unmanagedList, int listSize) = PrepareOptionList(options, ""); bool ok = InternetQueryOption(IntPtr.Zero, (int)InternetOptions.PerConnectionOption, unmanagedList, ref listSize); if (!ok) { @@ -260,13 +260,13 @@ public static WinINetSetting Query() proxy.Flags = (InternetPerConnectionFlags)o.Value.dwValue; break; case InternetPerConnectionOptionEnum.AutoConfigUrl: - proxy.AutoConfigUrl = Marshal.PtrToStringAuto(o.Value.pszValue); + proxy.AutoConfigUrl = Marshal.PtrToStringAuto(o.Value.pszValue) ?? ""; break; case InternetPerConnectionOptionEnum.ProxyBypass: - proxy.ProxyBypass = Marshal.PtrToStringAuto(o.Value.pszValue); + proxy.ProxyBypass = Marshal.PtrToStringAuto(o.Value.pszValue) ?? ""; break; case InternetPerConnectionOptionEnum.ProxyServer: - proxy.ProxyServer = Marshal.PtrToStringAuto(o.Value.pszValue); + proxy.ProxyServer = Marshal.PtrToStringAuto(o.Value.pszValue) ?? ""; break; default: break; @@ -343,7 +343,7 @@ private static void ClearOptionList(IntPtr list) private static void Exec(List options) { - Exec(options, null); + Exec(options, ""); foreach (string conn in RAS.GetAllConnections()) { Exec(options, conn); diff --git a/Shadowsocks.WPF/Utils/AutoStartup.cs b/Shadowsocks.WPF/Utils/AutoStartup.cs index 64ee77da5..b0f242a89 100644 --- a/Shadowsocks.WPF/Utils/AutoStartup.cs +++ b/Shadowsocks.WPF/Utils/AutoStartup.cs @@ -15,7 +15,7 @@ public static class AutoStartup public static bool Set(bool enabled) { - RegistryKey runKey = null; + RegistryKey? runKey = null; try { runKey = Registry.CurrentUser.CreateSubKey(registryRunKey, RegistryKeyPermissionCheck.ReadWriteSubTree); @@ -26,7 +26,7 @@ public static bool Set(bool enabled) } if (enabled) { - runKey.SetValue(Key, Process.GetCurrentProcess().MainModule?.FileName); + runKey.SetValue(Key, Utilities.ExecutablePath); } else { @@ -60,7 +60,7 @@ public static bool Set(bool enabled) public static bool Check() { - RegistryKey runKey = null; + RegistryKey? runKey = null; try { runKey = Registry.CurrentUser.CreateSubKey(registryRunKey, RegistryKeyPermissionCheck.ReadWriteSubTree); @@ -78,7 +78,7 @@ public static bool Check() continue; } // Remove other startup keys with the same executable path. fixes #3011 and also assures compatibility with older versions - if (Utilities.ExecutablePath.Equals(runKey.GetValue(valueName).ToString(), StringComparison.InvariantCultureIgnoreCase) + if (Utilities.ExecutablePath.Equals(runKey.GetValue(valueName)?.ToString(), StringComparison.InvariantCultureIgnoreCase) is bool matchedDuplicate && matchedDuplicate) { runKey.DeleteValue(valueName); diff --git a/Shadowsocks.WPF/Utils/FileManager.cs b/Shadowsocks.WPF/Utils/FileManager.cs index 3e69b0fa7..377b405aa 100644 --- a/Shadowsocks.WPF/Utils/FileManager.cs +++ b/Shadowsocks.WPF/Utils/FileManager.cs @@ -59,7 +59,7 @@ public static string NonExclusiveReadAllText(string path, Encoding encoding) catch (Exception ex) { LogHost.Default.Error(ex, ""); - throw ex; + throw; } } } diff --git a/Shadowsocks.WPF/Utils/IPCService.cs b/Shadowsocks.WPF/Utils/IPCService.cs index 6e3ad4e6d..42fab6840 100644 --- a/Shadowsocks.WPF/Utils/IPCService.cs +++ b/Shadowsocks.WPF/Utils/IPCService.cs @@ -21,7 +21,7 @@ internal class IPCService private const int OP_OPEN_URL = 1; private static readonly string PIPE_PATH = $"Shadowsocks\\{Utilities.ExecutablePath.GetHashCode()}"; - public event EventHandler OpenUrlRequested; + public event EventHandler? OpenUrlRequested; public async void RunServer() { diff --git a/Shadowsocks.WPF/Utils/ProtocolHandler.cs b/Shadowsocks.WPF/Utils/ProtocolHandler.cs index 9a0dbd2b4..ca2e35024 100644 --- a/Shadowsocks.WPF/Utils/ProtocolHandler.cs +++ b/Shadowsocks.WPF/Utils/ProtocolHandler.cs @@ -10,7 +10,7 @@ static class ProtocolHandler public static bool Set(bool enabled) { - RegistryKey ssURLAssociation = null; + RegistryKey? ssURLAssociation = null; try { @@ -59,7 +59,7 @@ public static bool Set(bool enabled) public static bool Check() { - RegistryKey ssURLAssociation = null; + RegistryKey? ssURLAssociation = null; try { ssURLAssociation = Registry.CurrentUser.OpenSubKey(ssURLRegKey, true); @@ -69,8 +69,8 @@ public static bool Check() return false; } - var shellOpen = ssURLAssociation.OpenSubKey("shell").OpenSubKey("open").OpenSubKey("command"); - return (string)shellOpen.GetValue("") == $"{Utilities.ExecutablePath} --open-url %1"; + var shellOpen = ssURLAssociation.OpenSubKey("shell")?.OpenSubKey("open")?.OpenSubKey("command"); + return shellOpen?.GetValue("") as string == $"{Utilities.ExecutablePath} --open-url %1"; } catch (Exception e) { diff --git a/Shadowsocks.WPF/Views/ServerSharingView.xaml.cs b/Shadowsocks.WPF/Views/ServerSharingView.xaml.cs index e4288a3a4..bf695e985 100644 --- a/Shadowsocks.WPF/Views/ServerSharingView.xaml.cs +++ b/Shadowsocks.WPF/Views/ServerSharingView.xaml.cs @@ -32,7 +32,7 @@ public ServerSharingView() view => view.urlTextBox.Text) .DisposeWith(disposables); - this.BindCommand(ViewModel, + this.BindCommand(ViewModel!, viewModel => viewModel.CopyLink, view => view.copyLinkButton) .DisposeWith(disposables); diff --git a/Shadowsocks.WPF/Views/VersionUpdatePromptView.xaml.cs b/Shadowsocks.WPF/Views/VersionUpdatePromptView.xaml.cs index ffaddbcd6..7e5404aa9 100644 --- a/Shadowsocks.WPF/Views/VersionUpdatePromptView.xaml.cs +++ b/Shadowsocks.WPF/Views/VersionUpdatePromptView.xaml.cs @@ -21,15 +21,15 @@ public VersionUpdatePromptView() view => releaseNotesMarkdownScrollViewer.Markdown) .DisposeWith(disposables);*/ - this.BindCommand(ViewModel, + this.BindCommand(ViewModel!, viewModel => viewModel.Update, view => view.updateButton) .DisposeWith(disposables); - this.BindCommand(ViewModel, + this.BindCommand(ViewModel!, viewModel => viewModel.SkipVersion, view => view.skipVersionButton) .DisposeWith(disposables); - this.BindCommand(ViewModel, + this.BindCommand(ViewModel!, viewModel => viewModel.NotNow, view => view.notNowButton) .DisposeWith(disposables);