@@ -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); | |||