apply suggestion

This commit is contained in:
qhy040404
2024-06-03 11:11:20 +08:00
parent 7d6a9691a2
commit 4bb7316ce5
6 changed files with 73 additions and 50 deletions

View File

@@ -0,0 +1,9 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Core.LifeCycle.InterProcess.Model;
internal sealed class ElevationStatusResponse
{
public bool IsElevated { get; set; }
}

View File

@@ -6,9 +6,9 @@ namespace Snap.Hutao.Core.LifeCycle.InterProcess;
internal enum PipePacketCommand : byte
{
None = 0,
Exit = 1,
RedirectActivation = 10,
RequestElevatedStatus = 11,
Exit = 30,
RequestElevationStatus = 11,
ResponseElevationStatus = 12,
}

View File

@@ -17,6 +17,26 @@ internal static class PipeStreamExtension
return content;
}
public static unsafe PipePacketHeader ReadPacket<TData>(this PipeStream stream, out TData? data)
where TData : class
{
data = default;
Span<byte> headerSpan = stackalloc byte[sizeof(PipePacketHeader)];
stream.ReadExactly(headerSpan);
fixed (byte* pHeader = headerSpan)
{
PipePacketHeader* header = (PipePacketHeader*)pHeader;
if (header->ContentType is PipePacketContentType.Json)
{
ReadOnlySpan<byte> content = stream.GetValidatedContent(header);
data = JsonSerializer.Deserialize<TData>(content);
}
return *header;
}
}
public static unsafe void WritePacket(this PipeStream stream, PipePacketHeader* header, byte[] content)
{
header->ContentLength = content.Length;

View File

@@ -2,6 +2,7 @@
// Licensed under the MIT license.
using Microsoft.Windows.AppLifecycle;
using Snap.Hutao.Core.LifeCycle.InterProcess.Model;
using System.IO.Pipes;
namespace Snap.Hutao.Core.LifeCycle.InterProcess;
@@ -17,30 +18,20 @@ internal sealed partial class PrivateNamedPipeClient : IDisposable
{
if (clientStream.TryConnectOnce())
{
bool serverElevated = false;
{
// Connect
PipePacketHeader connectPacket = default;
connectPacket.Version = 1;
connectPacket.Type = PipePacketType.Request;
connectPacket.Command = PipePacketCommand.RequestElevatedStatus;
connectPacket.Command = PipePacketCommand.RequestElevationStatus;
clientStream.Write(new(&connectPacket, sizeof(PipePacketHeader)));
}
{
// Get previous instance elevated status
Span<byte> headerSpan = stackalloc byte[sizeof(PipePacketHeader)];
clientStream.ReadExactly(headerSpan);
fixed (byte* pHeader = headerSpan)
{
PipePacketHeader* header = (PipePacketHeader*)pHeader;
ReadOnlySpan<byte> content = clientStream.GetValidatedContent(header);
serverElevated = JsonSerializer.Deserialize<bool>(content);
}
}
clientStream.ReadPacket(out ElevationStatusResponse? serverElevationStatus);
ArgumentNullException.ThrowIfNull(serverElevationStatus);
if (!serverElevated && runtimeOptions.IsElevated)
if (runtimeOptions.IsElevated && !serverElevationStatus.IsElevated)
{
// Kill previous instance to use current elevated instance
PipePacketHeader killPacket = default;

View File

@@ -1,6 +1,7 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Core.LifeCycle.InterProcess.Model;
using System.IO.Pipes;
using System.Security.AccessControl;
using System.Security.Principal;
@@ -74,42 +75,44 @@ internal sealed partial class PrivateNamedPipeServer : IDisposable
private unsafe void RunPacketSession(NamedPipeServerStream serverStream, CancellationToken token)
{
Span<byte> headerSpan = stackalloc byte[sizeof(PipePacketHeader)];
bool sessionTerminated = false;
while (serverStream.IsConnected && !sessionTerminated && !token.IsCancellationRequested)
while (serverStream.IsConnected && !token.IsCancellationRequested)
{
serverStream.ReadExactly(headerSpan);
fixed (byte* pHeader = headerSpan)
PipePacketHeader header = serverStream.ReadPacket(out HutaoActivationArguments? hutaoArgs);
switch ((header.Type, header.Command))
{
PipePacketHeader* header = (PipePacketHeader*)pHeader;
case (PipePacketType.Request, PipePacketCommand.RequestElevationStatus):
RespondElevationStatus();
break;
case (PipePacketType.Request, PipePacketCommand.RedirectActivation):
messageDispatcher.RedirectActivation(hutaoArgs);
break;
case (PipePacketType.SessionTermination, _):
serverStream.Disconnect();
if (header.Command is PipePacketCommand.Exit)
{
messageDispatcher.Exit();
}
switch ((header->Type, header->Command, header->ContentType))
{
case (PipePacketType.Request, PipePacketCommand.RequestElevatedStatus, _):
PipePacketHeader elevatedPacket = default;
elevatedPacket.Version = 1;
elevatedPacket.Type = PipePacketType.Response;
elevatedPacket.ContentType = PipePacketContentType.Json;
byte[] elevatedBytes = JsonSerializer.SerializeToUtf8Bytes(runtimeOptions.IsElevated);
serverStream.WritePacket(&elevatedPacket, elevatedBytes);
break;
case (PipePacketType.Request, PipePacketCommand.RedirectActivation, PipePacketContentType.Json):
ReadOnlySpan<byte> content = serverStream.GetValidatedContent(header);
messageDispatcher.RedirectActivation(JsonSerializer.Deserialize<HutaoActivationArguments>(content));
break;
case (PipePacketType.SessionTermination, _, _):
serverStream.Disconnect();
sessionTerminated = true;
if (header->Command is PipePacketCommand.Exit)
{
messageDispatcher.Exit();
}
return;
}
return;
}
}
void RespondElevationStatus()
{
PipePacketHeader elevatedPacket = default;
elevatedPacket.Version = 1;
elevatedPacket.Type = PipePacketType.Response;
elevatedPacket.Command = PipePacketCommand.ResponseElevationStatus;
elevatedPacket.ContentType = PipePacketContentType.Json;
ElevationStatusResponse resp = new()
{
IsElevated = runtimeOptions.IsElevated,
};
byte[] elevatedBytes = JsonSerializer.SerializeToUtf8Bytes(resp);
serverStream.WritePacket(&elevatedPacket, elevatedBytes);
serverStream.Flush();
}
}
}

View File

@@ -2,7 +2,7 @@
"profiles": {
"Snap.Hutao": {
"commandName": "MsixPackage",
"nativeDebugging": true,
"nativeDebugging": false,
"doNotLaunchApp": false,
"allowLocalNetworkLoopbackProperty": true
},