| @@ -16,11 +16,11 @@ namespace Shadowsocks.PAC | |||
| 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; | |||
| @@ -124,7 +124,7 @@ namespace Shadowsocks.PAC | |||
| { | |||
| 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 @@ namespace Shadowsocks.PAC | |||
| { | |||
| 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); | |||
| @@ -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<T>(string key) => LocExtension.GetLocalizedValue<T>($"{CallingAssemblyName}:Strings:{key}"); | |||
| } | |||
| @@ -6,6 +6,7 @@ using System.Net.Sockets; | |||
| namespace Shadowsocks.WPF.Services | |||
| { | |||
| #nullable disable | |||
| public class PortForwarder : StreamService | |||
| { | |||
| private readonly int _targetPort; | |||
| @@ -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 @@ namespace Shadowsocks.WPF.Services | |||
| 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 @@ namespace Shadowsocks.WPF.Services | |||
| 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) | |||
| @@ -42,7 +42,7 @@ namespace Shadowsocks.WPF.Services.SystemProxy | |||
| // 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 @@ namespace Shadowsocks.WPF.Services.SystemProxy | |||
| int entryNameSize = 0; | |||
| int lpSize = 0; | |||
| uint retval = ESuccess; | |||
| RasEntryName[] names = null; | |||
| RasEntryName[] names = Array.Empty<RasEntryName>(); | |||
| 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 @@ namespace Shadowsocks.WPF.Services.SystemProxy | |||
| names[i].dwSize = entryNameSize; | |||
| } | |||
| retval = RasEnumEntries(null, null, names, ref lpSize, out lpNames); | |||
| retval = RasEnumEntries("", "", names, ref lpSize, out lpNames); | |||
| } | |||
| if (retval == ESuccess) | |||
| @@ -136,7 +136,7 @@ namespace Shadowsocks.WPF.Services.SystemProxy | |||
| { | |||
| try | |||
| { | |||
| Record(); | |||
| initialSetting = Query(); | |||
| } | |||
| catch (DllNotFoundException) | |||
| { | |||
| @@ -153,9 +153,14 @@ namespace Shadowsocks.WPF.Services.SystemProxy | |||
| } | |||
| else | |||
| { | |||
| throw we; | |||
| throw; | |||
| } | |||
| } | |||
| finally | |||
| { | |||
| if (initialSetting == null) | |||
| initialSetting = new(); | |||
| } | |||
| } | |||
| public static void ProxyGlobal(string server, string bypass) | |||
| @@ -188,11 +193,6 @@ namespace Shadowsocks.WPF.Services.SystemProxy | |||
| Exec(options); | |||
| } | |||
| private static void Record() | |||
| { | |||
| initialSetting ??= Query(); | |||
| } | |||
| public static void Restore() | |||
| { | |||
| Set(initialSetting); | |||
| @@ -231,7 +231,7 @@ namespace Shadowsocks.WPF.Services.SystemProxy | |||
| 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 @@ namespace Shadowsocks.WPF.Services.SystemProxy | |||
| 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 @@ namespace Shadowsocks.WPF.Services.SystemProxy | |||
| private static void Exec(List<InternetPerConnectionOption> options) | |||
| { | |||
| Exec(options, null); | |||
| Exec(options, ""); | |||
| foreach (string conn in RAS.GetAllConnections()) | |||
| { | |||
| Exec(options, conn); | |||
| @@ -15,7 +15,7 @@ namespace Shadowsocks.WPF.Utils | |||
| public static bool Set(bool enabled) | |||
| { | |||
| RegistryKey runKey = null; | |||
| RegistryKey? runKey = null; | |||
| try | |||
| { | |||
| runKey = Registry.CurrentUser.CreateSubKey(registryRunKey, RegistryKeyPermissionCheck.ReadWriteSubTree); | |||
| @@ -26,7 +26,7 @@ namespace Shadowsocks.WPF.Utils | |||
| } | |||
| if (enabled) | |||
| { | |||
| runKey.SetValue(Key, Process.GetCurrentProcess().MainModule?.FileName); | |||
| runKey.SetValue(Key, Utilities.ExecutablePath); | |||
| } | |||
| else | |||
| { | |||
| @@ -60,7 +60,7 @@ namespace Shadowsocks.WPF.Utils | |||
| public static bool Check() | |||
| { | |||
| RegistryKey runKey = null; | |||
| RegistryKey? runKey = null; | |||
| try | |||
| { | |||
| runKey = Registry.CurrentUser.CreateSubKey(registryRunKey, RegistryKeyPermissionCheck.ReadWriteSubTree); | |||
| @@ -78,7 +78,7 @@ namespace Shadowsocks.WPF.Utils | |||
| 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); | |||
| @@ -59,7 +59,7 @@ namespace Shadowsocks.WPF.Utils | |||
| catch (Exception ex) | |||
| { | |||
| LogHost.Default.Error(ex, ""); | |||
| throw ex; | |||
| throw; | |||
| } | |||
| } | |||
| } | |||
| @@ -21,7 +21,7 @@ namespace Shadowsocks.WPF.Utils | |||
| private const int OP_OPEN_URL = 1; | |||
| private static readonly string PIPE_PATH = $"Shadowsocks\\{Utilities.ExecutablePath.GetHashCode()}"; | |||
| public event EventHandler<RequestAddUrlEventArgs> OpenUrlRequested; | |||
| public event EventHandler<RequestAddUrlEventArgs>? OpenUrlRequested; | |||
| public async void RunServer() | |||
| { | |||
| @@ -10,7 +10,7 @@ namespace Shadowsocks.WPF.Utils | |||
| public static bool Set(bool enabled) | |||
| { | |||
| RegistryKey ssURLAssociation = null; | |||
| RegistryKey? ssURLAssociation = null; | |||
| try | |||
| { | |||
| @@ -59,7 +59,7 @@ namespace Shadowsocks.WPF.Utils | |||
| public static bool Check() | |||
| { | |||
| RegistryKey ssURLAssociation = null; | |||
| RegistryKey? ssURLAssociation = null; | |||
| try | |||
| { | |||
| ssURLAssociation = Registry.CurrentUser.OpenSubKey(ssURLRegKey, true); | |||
| @@ -69,8 +69,8 @@ namespace Shadowsocks.WPF.Utils | |||
| 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) | |||
| { | |||
| @@ -32,7 +32,7 @@ namespace Shadowsocks.WPF.Views | |||
| view => view.urlTextBox.Text) | |||
| .DisposeWith(disposables); | |||
| this.BindCommand(ViewModel, | |||
| this.BindCommand(ViewModel!, | |||
| viewModel => viewModel.CopyLink, | |||
| view => view.copyLinkButton) | |||
| .DisposeWith(disposables); | |||
| @@ -21,15 +21,15 @@ namespace Shadowsocks.WPF.Views | |||
| 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); | |||