mirror of
https://github.com/HolographicHat/Yae.git
synced 2026-05-20 20:55:46 +08:00
Merge pull request #144 from Lightczx/master
This commit is contained in:
@@ -0,0 +1,104 @@
|
|||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using System.Threading;
|
||||||
|
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
|
||||||
|
|
||||||
|
namespace YaeAchievement.SourceGeneration;
|
||||||
|
|
||||||
|
[Generator(LanguageNames.CSharp)]
|
||||||
|
public sealed class MinHookAttachGenerator : IIncrementalGenerator
|
||||||
|
{
|
||||||
|
public void Initialize(IncrementalGeneratorInitializationContext context)
|
||||||
|
{
|
||||||
|
IncrementalValueProvider<ImmutableArray<AttachInfo>> provider = context.SyntaxProvider.CreateSyntaxProvider(Filter, Transform).Collect();
|
||||||
|
context.RegisterSourceOutput(provider, Generate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool Filter(SyntaxNode node, CancellationToken token)
|
||||||
|
{
|
||||||
|
return node is InvocationExpressionSyntax
|
||||||
|
{
|
||||||
|
Expression: MemberAccessExpressionSyntax
|
||||||
|
{
|
||||||
|
Expression: IdentifierNameSyntax { Identifier.Text: "MinHook" },
|
||||||
|
Name.Identifier.Text: "Attach"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AttachInfo Transform(GeneratorSyntaxContext context, CancellationToken token)
|
||||||
|
{
|
||||||
|
InvocationExpressionSyntax invocation = (InvocationExpressionSyntax)context.Node;
|
||||||
|
SeparatedSyntaxList<ArgumentSyntax> args = invocation.ArgumentList.Arguments;
|
||||||
|
if (args.Count is not 3)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
string type = context.SemanticModel.GetTypeInfo(args[0].Expression).Type?.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(type))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new()
|
||||||
|
{
|
||||||
|
MinimallyQualifiedType = type,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Generate(SourceProductionContext context, ImmutableArray<AttachInfo> infoArray)
|
||||||
|
{
|
||||||
|
CompilationUnitSyntax unit = CompilationUnit()
|
||||||
|
.WithMembers(List<MemberDeclarationSyntax>(
|
||||||
|
[
|
||||||
|
FileScopedNamespaceDeclaration(ParseName("Yae.Utilities")),
|
||||||
|
ClassDeclaration("MinHook")
|
||||||
|
.WithModifiers(TokenList(Token(SyntaxKind.InternalKeyword), Token(SyntaxKind.StaticKeyword), Token(SyntaxKind.PartialKeyword)))
|
||||||
|
.WithMembers(List(GenerateMethods(infoArray)))
|
||||||
|
]));
|
||||||
|
|
||||||
|
context.AddSource("MinHook.Attach.g.cs", unit.NormalizeWhitespace().ToFullString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<MemberDeclarationSyntax> GenerateMethods(ImmutableArray<AttachInfo> infoArray)
|
||||||
|
{
|
||||||
|
foreach (AttachInfo info in infoArray)
|
||||||
|
{
|
||||||
|
TypeSyntax type = ParseTypeName(info.MinimallyQualifiedType);
|
||||||
|
|
||||||
|
yield return MethodDeclaration(PredefinedType(Token(SyntaxKind.VoidKeyword)), Identifier("Attach"))
|
||||||
|
.WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword), Token(SyntaxKind.UnsafeKeyword)))
|
||||||
|
.WithParameterList(ParameterList(SeparatedList(
|
||||||
|
[
|
||||||
|
Parameter(Identifier("origin")).WithType(type),
|
||||||
|
Parameter(Identifier("handler")).WithType(type),
|
||||||
|
Parameter(Identifier("trampoline")).WithType(type).WithModifiers(TokenList(Token(SyntaxKind.OutKeyword)))
|
||||||
|
])))
|
||||||
|
.WithBody(Block(List<StatementSyntax>(
|
||||||
|
[
|
||||||
|
ExpressionStatement(InvocationExpression(IdentifierName("Attach"))
|
||||||
|
.WithArgumentList(ArgumentList(SeparatedList(
|
||||||
|
[
|
||||||
|
Argument(CastExpression(IdentifierName("nint"), IdentifierName("origin"))),
|
||||||
|
Argument(CastExpression(IdentifierName("nint"), IdentifierName("handler"))),
|
||||||
|
Argument(DeclarationExpression(IdentifierName("nint"), SingleVariableDesignation(Identifier("trampoline1"))))
|
||||||
|
.WithRefKindKeyword(Token(SyntaxKind.OutKeyword))
|
||||||
|
])))),
|
||||||
|
ExpressionStatement(AssignmentExpression(
|
||||||
|
SyntaxKind.SimpleAssignmentExpression,
|
||||||
|
IdentifierName("trampoline"),
|
||||||
|
CastExpression(type, IdentifierName("trampoline1"))))
|
||||||
|
])));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private record AttachInfo
|
||||||
|
{
|
||||||
|
public required string MinimallyQualifiedType { get; init; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<LangVersion>preview</LangVersion>
|
||||||
|
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.14.0" />
|
||||||
|
<PackageReference Include="PolySharp" Version="1.15.0">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
<Solution>
|
<Solution>
|
||||||
<Project Path="YaeAchievementLib\YaeAchievementLib.csproj" Type="Classic C#" />
|
<Project Path="YaeAchievement.SourceGeneration/YaeAchievement.SourceGeneration/YaeAchievement.SourceGeneration.csproj" Id="3c1c5723-c1e4-4119-9ad5-de5a415c5980" />
|
||||||
<Project Path="YaeAchievement\YaeAchievement.csproj" Type="Classic C#" />
|
<Project Path="YaeAchievementLib\YaeAchievementLib.csproj" />
|
||||||
|
<Project Path="YaeAchievement\YaeAchievement.csproj" />
|
||||||
</Solution>
|
</Solution>
|
||||||
@@ -25,20 +25,20 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<DirectPInvoke Include="NTDLL"/>
|
<DirectPInvoke Include="NTDLL" />
|
||||||
<DirectPInvoke Include="USER32"/>
|
<DirectPInvoke Include="USER32" />
|
||||||
<DirectPInvoke Include="KERNEL32"/>
|
<DirectPInvoke Include="KERNEL32" />
|
||||||
<DirectPInvoke Include="libMinHook.x64"/>
|
<DirectPInvoke Include="libMinHook.x64" />
|
||||||
<NativeLibrary Include="lib\libMinHook.x64.lib"/>
|
<NativeLibrary Include="lib\libMinHook.x64.lib" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AssemblyAttribute Include="System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute"/>
|
<AssemblyAttribute Include="System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Using Include="System.Diagnostics"/>
|
<Using Include="System.Diagnostics" />
|
||||||
<Using Include="System.Diagnostics.CodeAnalysis"/>
|
<Using Include="System.Diagnostics.CodeAnalysis" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
@@ -54,11 +54,18 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="$(PublishDir)\$(TargetName)$(NativeBinaryExt)" Pack="true" PackagePath="runtimes\win-x64\native" Visible="false"/>
|
<None Include="$(PublishDir)\$(TargetName)$(NativeBinaryExt)" Pack="true" PackagePath="runtimes\win-x64\native" Visible="false" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference OutputItemType="Analyzer" Include="..\YaeAchievement.SourceGeneration\YaeAchievement.SourceGeneration\YaeAchievement.SourceGeneration.csproj">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<Target Name="GenerateNuGetPackage" AfterTargets="CopyNativeBinary">
|
<Target Name="GenerateNuGetPackage" AfterTargets="CopyNativeBinary">
|
||||||
<Exec Command="dotnet pack --no-build --nologo" UseUtf8Encoding="Always" EchoOff="true"/>
|
<Exec Command="dotnet pack --no-build --nologo" UseUtf8Encoding="Always" EchoOff="true" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -159,30 +159,6 @@ internal static partial class MinHook {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: auto gen
|
|
||||||
public static unsafe void Attach(delegate*unmanaged<byte*, int, ushort> origin, delegate*unmanaged<byte*, int, ushort> handler, out delegate*unmanaged<byte*, int, ushort> trampoline) {
|
|
||||||
Attach((nint) origin, (nint) handler, out var trampoline1);
|
|
||||||
trampoline = (delegate*unmanaged<byte*, int, ushort>) trampoline1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo: auto gen
|
|
||||||
public static unsafe void Attach(delegate*unmanaged<nint, int, double, double, int, void> origin, delegate*unmanaged<nint, int, double, double, int, void> handler, out delegate*unmanaged<nint, int, double, double, int, void> trampoline) {
|
|
||||||
Attach((nint) origin, (nint) handler, out var trampoline1);
|
|
||||||
trampoline = (delegate*unmanaged<nint, int, double, double, int, void>) trampoline1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo: auto gen
|
|
||||||
public static unsafe void Attach(delegate*unmanaged<nint, void> origin, delegate*unmanaged<nint, void> handler, out delegate*unmanaged<nint, void> trampoline) {
|
|
||||||
Attach((nint) origin, (nint) handler, out var trampoline1);
|
|
||||||
trampoline = (delegate*unmanaged<nint, void>) trampoline1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo: auto gen
|
|
||||||
public static unsafe void Attach(delegate*unmanaged<int, void*, int, int> origin, delegate*unmanaged<int, void*, int, int> handler, out delegate*unmanaged<int, void*, int, int> trampoline) {
|
|
||||||
Attach((nint) origin, (nint) handler, out var trampoline1);
|
|
||||||
trampoline = (delegate*unmanaged<int, void*, int, int>) trampoline1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Attach(nint origin, nint handler, out nint trampoline) {
|
public static void Attach(nint origin, nint handler, out nint trampoline) {
|
||||||
uint result;
|
uint result;
|
||||||
if ((result = MinHookCreate(origin, handler, out trampoline)) != 0) {
|
if ((result = MinHookCreate(origin, handler, out trampoline)) != 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user