code style

This commit is contained in:
DismissedLight
2024-01-27 13:01:56 +08:00
parent c4f3eb68e8
commit 196bbb54c3
7 changed files with 98 additions and 76 deletions

View File

@@ -1,4 +1,4 @@
// Copyright (c) DGP Studio. All rights reserved.
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using CommunityToolkit.Mvvm.ComponentModel;
@@ -14,50 +14,34 @@ internal sealed partial class DynamicHttpProxy : ObservableObject, IWebProxy, ID
{
private const string ProxySettingPath = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections";
private static readonly MethodInfo ConstructSystemProxyMethod;
private static readonly Lazy<MethodInfo> LazyConstructSystemProxyMethod = new(GetConstructSystemProxyMethod);
private readonly IServiceProvider serviceProvider;
private readonly RegistryWatcher watcher;
private IWebProxy innerProxy = default!;
[SuppressMessage("", "CA1810")]
static DynamicHttpProxy()
public DynamicHttpProxy(IServiceProvider serviceProvider)
{
Type? systemProxyInfoType = typeof(System.Net.Http.SocketsHttpHandler).Assembly.GetType("System.Net.Http.SystemProxyInfo");
ArgumentNullException.ThrowIfNull(systemProxyInfoType);
this.serviceProvider = serviceProvider;
UpdateInnerProxy();
MethodInfo? constructSystemProxyMethod = systemProxyInfoType.GetMethod("ConstructSystemProxy", BindingFlags.Static | BindingFlags.Public);
ArgumentNullException.ThrowIfNull(constructSystemProxyMethod);
ConstructSystemProxyMethod = constructSystemProxyMethod;
}
public DynamicHttpProxy()
{
UpdateProxy();
watcher = new(ProxySettingPath, OnProxyChanged);
watcher = new(ProxySettingPath, OnSystemProxySettingsChanged);
watcher.Start();
}
/// <inheritdoc/>
public ICredentials? Credentials
{
get => InnerProxy.Credentials;
set => InnerProxy.Credentials = value;
}
public string CurrentProxy
public string CurrentProxyUri
{
get
{
Uri? proxyUri = GetProxy(HutaoEndpoints.Website(string.Empty).ToUri());
Uri? proxyUri = GetProxy("https://hut.ao".ToUri());
return proxyUri is null
? SH.ViewPageFeedbackCurrentProxyNoProxyDescription
: proxyUri.AbsoluteUri;
}
}
private IWebProxy InnerProxy
public IWebProxy InnerProxy
{
get => innerProxy;
@@ -74,6 +58,12 @@ internal sealed partial class DynamicHttpProxy : ObservableObject, IWebProxy, ID
}
}
public ICredentials? Credentials
{
get => InnerProxy.Credentials;
set => InnerProxy.Credentials = value;
}
public Uri? GetProxy(Uri destination)
{
return InnerProxy.GetProxy(destination);
@@ -90,17 +80,30 @@ internal sealed partial class DynamicHttpProxy : ObservableObject, IWebProxy, ID
watcher.Dispose();
}
public void OnProxyChanged()
public void OnSystemProxySettingsChanged()
{
UpdateProxy();
UpdateInnerProxy();
Ioc.Default.GetRequiredService<ITaskContext>().InvokeOnMainThread(() => OnPropertyChanged(nameof(CurrentProxy)));
// TaskContext can't be injected directly since there are some recursive dependencies.
ITaskContext taskContext = serviceProvider.GetRequiredService<ITaskContext>();
taskContext.BeginInvokeOnMainThread(() => OnPropertyChanged(nameof(CurrentProxyUri)));
}
private static MethodInfo GetConstructSystemProxyMethod()
{
Type? systemProxyInfoType = typeof(System.Net.Http.SocketsHttpHandler).Assembly.GetType("System.Net.Http.SystemProxyInfo");
ArgumentNullException.ThrowIfNull(systemProxyInfoType);
MethodInfo? constructSystemProxyMethod = systemProxyInfoType.GetMethod("ConstructSystemProxy", BindingFlags.Static | BindingFlags.Public);
ArgumentNullException.ThrowIfNull(constructSystemProxyMethod);
return constructSystemProxyMethod;
}
[MemberNotNull(nameof(innerProxy))]
private void UpdateProxy()
private void UpdateInnerProxy()
{
IWebProxy? proxy = ConstructSystemProxyMethod.Invoke(default, default) as IWebProxy;
IWebProxy? proxy = LazyConstructSystemProxyMethod.Value.Invoke(default, default) as IWebProxy;
ArgumentNullException.ThrowIfNull(proxy);
InnerProxy = proxy;

View File

@@ -5,72 +5,81 @@ using CommunityToolkit.Mvvm.ComponentModel;
using Snap.Hutao.Win32.Foundation;
using Snap.Hutao.Win32.NetworkManagement.WindowsFirewall;
using Snap.Hutao.Win32.Security;
using System.Runtime.InteropServices;
using static Snap.Hutao.Win32.AdvApi32;
using static Snap.Hutao.Win32.ApiMsWinNetIsolation;
using static Snap.Hutao.Win32.Macros;
namespace Snap.Hutao.Core.IO.Http.Loopback;
[Injection(InjectAs.Singleton)]
internal sealed unsafe class LoopbackManager : ObservableObject, IDisposable
internal sealed unsafe class LoopbackManager : ObservableObject
{
private readonly INET_FIREWALL_APP_CONTAINER* pContainers;
private readonly INET_FIREWALL_APP_CONTAINER* pHutaoContainer;
private readonly RuntimeOptions runtimeOptions;
private readonly ITaskContext taskContext;
private readonly SID hutaoContainerSID;
private bool isLoopbackEnabled;
public LoopbackManager(IServiceProvider serviceProvider)
{
runtimeOptions = serviceProvider.GetRequiredService<RuntimeOptions>();
taskContext = serviceProvider.GetRequiredService<ITaskContext>();
NetworkIsolationEnumAppContainers(NETISO_FLAG.NETISO_FLAG_MAX, out uint acCount, out pContainers);
for (uint i = 0; i < acCount; i++)
INET_FIREWALL_APP_CONTAINER* pContainers = default;
try
{
INET_FIREWALL_APP_CONTAINER* pContainer = pContainers + i;
if (new string(pContainer->appContainerName) == runtimeOptions.FamilyName)
WIN32_ERROR error = NetworkIsolationEnumAppContainers(NETISO_FLAG.NETISO_FLAG_MAX, out uint acCount, out pContainers);
Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(error));
for (uint i = 0; i < acCount; i++)
{
pHutaoContainer = pContainer;
break;
INET_FIREWALL_APP_CONTAINER* pContainer = pContainers + i;
ReadOnlySpan<char> appContainerName = MemoryMarshal.CreateReadOnlySpanFromNullTerminated(pContainer->appContainerName);
if (appContainerName.Equals(runtimeOptions.FamilyName))
{
hutaoContainerSID = *pContainer->appContainerSid;
break;
}
}
}
NetworkIsolationGetAppContainerConfig(out uint accCount, out SID_AND_ATTRIBUTES* pSids);
for (uint i = 0; i < accCount; i++)
finally
{
if (EqualSid(new PSID { Value = pHutaoContainer->appContainerSid }, (pSids + i)->Sid))
uint retVal = NetworkIsolationFreeAppContainers(pContainers);
Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(*(WIN32_ERROR*)&retVal));
}
WIN32_ERROR error2 = NetworkIsolationGetAppContainerConfig(out uint accCount, out SID_AND_ATTRIBUTES* pSids);
Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(error2));
fixed (SID* phutaoContainerSID = &hutaoContainerSID)
{
for (uint i = 0; i < accCount; i++)
{
IsLoopbackEnabled = true;
break;
if (EqualSid(phutaoContainerSID, (pSids + i)->Sid))
{
IsLoopbackEnabled = true;
break;
}
}
}
}
public bool IsLoopbackEnabled { get; private set; }
public bool IsLoopbackEnabled { get => isLoopbackEnabled; private set => SetProperty(ref isLoopbackEnabled, value); }
public void EnableLoopback()
{
List<SID_AND_ATTRIBUTES> sids = [];
NetworkIsolationGetAppContainerConfig(out uint accCount, out SID_AND_ATTRIBUTES* pSids);
List<SID_AND_ATTRIBUTES> sids = new((int)(accCount + 1));
for (uint i = 0; i < accCount; i++)
{
sids.Add(*(pSids + i));
}
sids.Add(new SID_AND_ATTRIBUTES
fixed (SID* phutaoContainerSID = &hutaoContainerSID)
{
Sid = new PSID { Value = pHutaoContainer->appContainerSid },
Attributes = 0,
});
IsLoopbackEnabled = NetworkIsolationSetAppContainerConfig(sids.ToArray()) is 0U;
taskContext.InvokeOnMainThread(() => OnPropertyChanged(nameof(IsLoopbackEnabled)));
}
public void Dispose()
{
_ = NetworkIsolationFreeAppContainers(pContainers);
SID_AND_ATTRIBUTES sidAndAttributes = default;
sidAndAttributes.Sid = phutaoContainerSID;
sids.Add(sidAndAttributes);
IsLoopbackEnabled = NetworkIsolationSetAppContainerConfig(CollectionsMarshal.AsSpan(sids)) is WIN32_ERROR.ERROR_SUCCESS;
}
}
}

View File

@@ -130,6 +130,7 @@ internal sealed partial class FeedbackViewModel : Abstraction.ViewModel
if (result is ContentDialogResult.Primary)
{
await taskContext.SwitchToMainThreadAsync();
LoopbackManager.EnableLoopback();
}
}

View File

@@ -13,8 +13,8 @@ namespace Snap.Hutao.Win32;
[SuppressMessage("", "SYSLIB1054")]
internal static class AdvApi32
{
[DllImport("ADVAPI32.dll", ExactSpelling = true)]
[SupportedOSPlatform("windows5.0")]
[DllImport("ADVAPI32.dll", ExactSpelling = true, SetLastError = true)]
[SupportedOSPlatform("windows5.1.2600")]
public static extern BOOL EqualSid(PSID pSid1, PSID pSid2);
[DllImport("ADVAPI32.dll", ExactSpelling = true)]

View File

@@ -1,6 +1,7 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Win32.Foundation;
using Snap.Hutao.Win32.NetworkManagement.WindowsFirewall;
using Snap.Hutao.Win32.Security;
using System.Diagnostics;
@@ -19,13 +20,14 @@ internal static class ApiMsWinNetIsolation
public static unsafe extern uint NetworkIsolationEnumAppContainers(uint Flags, uint* pdwNumPublicAppCs, INET_FIREWALL_APP_CONTAINER** ppPublicAppCs);
[DebuggerStepThrough]
public static unsafe uint NetworkIsolationEnumAppContainers(NETISO_FLAG Flags, out uint dwNumPublicAppCs, out INET_FIREWALL_APP_CONTAINER* pPublicAppCs)
public static unsafe WIN32_ERROR NetworkIsolationEnumAppContainers(NETISO_FLAG Flags, out uint dwNumPublicAppCs, out INET_FIREWALL_APP_CONTAINER* pPublicAppCs)
{
fixed (uint* pdwNumPublicAppCs = &dwNumPublicAppCs)
{
fixed (INET_FIREWALL_APP_CONTAINER** ppPublicAppCs = &pPublicAppCs)
{
return NetworkIsolationEnumAppContainers((uint)Flags, pdwNumPublicAppCs, ppPublicAppCs);
uint retVal = NetworkIsolationEnumAppContainers((uint)Flags, pdwNumPublicAppCs, ppPublicAppCs);
return *(WIN32_ERROR*)&retVal;
}
}
}
@@ -35,11 +37,12 @@ internal static class ApiMsWinNetIsolation
public static unsafe extern uint NetworkIsolationFreeAppContainers(INET_FIREWALL_APP_CONTAINER* pPublicAppCs);
[DebuggerStepThrough]
public static unsafe uint NetworkIsolationFreeAppContainers(ref readonly INET_FIREWALL_APP_CONTAINER publicAppCs)
public static unsafe WIN32_ERROR NetworkIsolationFreeAppContainers(ref readonly INET_FIREWALL_APP_CONTAINER publicAppCs)
{
fixed (INET_FIREWALL_APP_CONTAINER* pPublicAppCs = &publicAppCs)
{
return NetworkIsolationFreeAppContainers(pPublicAppCs);
uint retVal = NetworkIsolationFreeAppContainers(pPublicAppCs);
return *(WIN32_ERROR*)&retVal;
}
}
@@ -48,13 +51,14 @@ internal static class ApiMsWinNetIsolation
public static unsafe extern uint NetworkIsolationGetAppContainerConfig(uint* pdwNumPublicAppCs, SID_AND_ATTRIBUTES** appContainerSids);
[DebuggerStepThrough]
public static unsafe uint NetworkIsolationGetAppContainerConfig(out uint dwNumPublicAppCs, out SID_AND_ATTRIBUTES* appContainerSids)
public static unsafe WIN32_ERROR NetworkIsolationGetAppContainerConfig(out uint dwNumPublicAppCs, out SID_AND_ATTRIBUTES* appContainerSids)
{
fixed (uint* pdwNumPublicAppCs = &dwNumPublicAppCs)
{
fixed (SID_AND_ATTRIBUTES** pAppContainerSids = &appContainerSids)
{
return NetworkIsolationGetAppContainerConfig(pdwNumPublicAppCs, pAppContainerSids);
uint retVal = NetworkIsolationGetAppContainerConfig(pdwNumPublicAppCs, pAppContainerSids);
return *(WIN32_ERROR*)&retVal;
}
}
}
@@ -64,11 +68,12 @@ internal static class ApiMsWinNetIsolation
public static unsafe extern uint NetworkIsolationSetAppContainerConfig(uint dwNumPublicAppCs, SID_AND_ATTRIBUTES* appContainerSids);
[DebuggerStepThrough]
public static unsafe uint NetworkIsolationSetAppContainerConfig(ReadOnlySpan<SID_AND_ATTRIBUTES> appContainerSids)
public static unsafe WIN32_ERROR NetworkIsolationSetAppContainerConfig(ReadOnlySpan<SID_AND_ATTRIBUTES> appContainerSids)
{
fixed (SID_AND_ATTRIBUTES* pAppContainerSids = appContainerSids)
{
return NetworkIsolationSetAppContainerConfig((uint)appContainerSids.Length, pAppContainerSids);
uint retVal = NetworkIsolationSetAppContainerConfig((uint)appContainerSids.Length, pAppContainerSids);
return *(WIN32_ERROR*)&retVal;
}
}
}

View File

@@ -3,8 +3,8 @@
namespace Snap.Hutao.Win32.Foundation;
internal unsafe struct FlexibleArray<T>
where T : unmanaged
internal unsafe struct FlexibleArray<TElement>
where TElement : unmanaged
{
public T* Reference;
public TElement* Reference;
}

View File

@@ -1,9 +1,13 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Win32.Security;
namespace Snap.Hutao.Win32.Foundation;
internal struct PSID
{
public unsafe void* Value;
public static unsafe implicit operator PSID(SID* value) => *(PSID*)&value;
}