mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
code style
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,6 +130,7 @@ internal sealed partial class FeedbackViewModel : Abstraction.ViewModel
|
||||
|
||||
if (result is ContentDialogResult.Primary)
|
||||
{
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
LoopbackManager.EnableLoopback();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user