From e2bc3ed350f067be55b125d259af3c9eb33db9b6 Mon Sep 17 00:00:00 2001 From: unknown6656 Date: Thu, 30 Jul 2020 01:43:46 +0200 Subject: [PATCH] Continued implementing DllCall (#9) --- new/AutoItInterpreter/AssemblyInfo.cs | 12 +-- .../Plugins.Au3Framework.Functions.cs | 18 ++-- new/AutoItInterpreter/IsExternalInit.cs | 9 ++ .../Properties/launchSettings.json | 3 +- .../Runtime/DelegateBuilder.cs | 99 ++++++++++++++----- new/AutoItInterpreter/version.txt | 4 +- new/test/test.au3 | 4 +- new/util/AutoIt3.Common/ExternalServices.cs | 16 +-- 8 files changed, 115 insertions(+), 50 deletions(-) create mode 100644 new/AutoItInterpreter/IsExternalInit.cs diff --git a/new/AutoItInterpreter/AssemblyInfo.cs b/new/AutoItInterpreter/AssemblyInfo.cs index 44681c65..6c3aaaef 100644 --- a/new/AutoItInterpreter/AssemblyInfo.cs +++ b/new/AutoItInterpreter/AssemblyInfo.cs @@ -1,15 +1,15 @@ ////////////////////////////////////////////////////////////////////////// -// Auto-generated 2020-07-29 20:12:29.557 // +// Auto-generated 2020-07-30 01:16:51.908 // // ANY CHANGES TO THIS DOCUMENT WILL BE LOST UPON RE-GENERATION // ////////////////////////////////////////////////////////////////////////// using System.Reflection; using System; -[assembly: AssemblyVersion("0.6.1303.7331")] -[assembly: AssemblyFileVersion("0.6.1303.7331")] -[assembly: AssemblyInformationalVersion("v.0.6.1303.7331, commit: 7a77da24ffb83f015e215bf2a17c4d03c3336e15")] +[assembly: AssemblyVersion("0.6.1321.7332")] +[assembly: AssemblyFileVersion("0.6.1321.7332")] +[assembly: AssemblyInformationalVersion("v.0.6.1321.7332, commit: f99805ac759f04bfb201af9df4451b4f2f964292")] [assembly: AssemblyCompany("Unknown6656")] [assembly: AssemblyCopyright("Copyright © 2018 - 2020, Unknown6656")] [assembly: AssemblyProduct("AutoIt3 Interpreter by Unknown6656")] @@ -35,11 +35,11 @@ public static class __module__ /// /// The interpreter's current version. /// - public static Version? InterpreterVersion { get; } = Version.Parse("0.6.1303.7331"); + public static Version? InterpreterVersion { get; } = Version.Parse("0.6.1321.7332"); /// /// The Git hash associated with the current build. /// - public const string GitHash = "7a77da24ffb83f015e215bf2a17c4d03c3336e15"; + public const string GitHash = "f99805ac759f04bfb201af9df4451b4f2f964292"; /// /// The URL of this project's Git(Hub) repository. /// diff --git a/new/AutoItInterpreter/Extensibility/Plugins.Au3Framework.Functions.cs b/new/AutoItInterpreter/Extensibility/Plugins.Au3Framework.Functions.cs index e8b87d3b..cc19d58b 100644 --- a/new/AutoItInterpreter/Extensibility/Plugins.Au3Framework.Functions.cs +++ b/new/AutoItInterpreter/Extensibility/Plugins.Au3Framework.Functions.cs @@ -20,6 +20,8 @@ using Unknown6656.AutoIt3.COM; using Unknown6656.Common; using Unknown6656.IO; +using System.Runtime.CompilerServices; +using System.Reflection; namespace Unknown6656.AutoIt3.Extensibility.Plugins.Au3Framework { @@ -59,7 +61,7 @@ public sealed class FrameworkFunctions ProvidedNativeFunction.Create(nameof(AscW), 1, AscW), ProvidedNativeFunction.Create(nameof(Chr), 1, Chr), ProvidedNativeFunction.Create(nameof(ChrW), 1, ChrW), - ProvidedNativeFunction.Create(nameof(Beep), OS.Window, 0, 2, Beep, 500m, 1000m), + ProvidedNativeFunction.Create(nameof(Beep), OS.Windows, 0, 2, Beep, 500m, 1000m), ProvidedNativeFunction.Create(nameof(BitAND), 2, 256, BitAND, Enumerable.Repeat((Variant)0xffffffff, 255).ToArray()), ProvidedNativeFunction.Create(nameof(BitOR), 2, 256, BitOR), ProvidedNativeFunction.Create(nameof(BitXOR), 2, 256, BitXOR), @@ -188,10 +190,10 @@ public sealed class FrameworkFunctions ProvidedNativeFunction.Create(nameof(ProcessWaitClose), 1, 2, ProcessWaitClose, Variant.Zero), ProvidedNativeFunction.Create(nameof(Random), 0, 3, Random, Variant.Zero, 1, Variant.False), ProvidedNativeFunction.Create(nameof(RegDelete), OS.Windows, 1, 2, RegDelete, Variant.Default), - ProvidedNativeFunction.Create(nameof(RegEnumKey), OS.Window, 2, RegEnumKey), - ProvidedNativeFunction.Create(nameof(RegEnumVal), OS.Window, 2, RegEnumVal), - ProvidedNativeFunction.Create(nameof(RegRead), OS.Window, 2, RegRead), - ProvidedNativeFunction.Create(nameof(RegWrite), OS.Window, 1, 4, RegWrite, Variant.Default, Variant.Default, Variant.Default), + ProvidedNativeFunction.Create(nameof(RegEnumKey), OS.Windows, 2, RegEnumKey), + ProvidedNativeFunction.Create(nameof(RegEnumVal), OS.Windows, 2, RegEnumVal), + ProvidedNativeFunction.Create(nameof(RegRead), OS.Windows, 2, RegRead), + ProvidedNativeFunction.Create(nameof(RegWrite), OS.Windows, 1, 4, RegWrite, Variant.Default, Variant.Default, Variant.Default), ProvidedNativeFunction.Create(nameof(Shutdown), 1, Shutdown), ProvidedNativeFunction.Create(nameof(SRandom), 1, SRandom), ProvidedNativeFunction.Create(nameof(StringAddCR), 1, StringAddCR), @@ -685,10 +687,10 @@ internal static FunctionReturnValue DllCall(CallFrame frame, Variant[] args) return FunctionReturnValue.Error(3); else if (frame.Interpreter.ParserProvider.DLLStructParser.TryParse(raw_signature, out ParserResult? result) && result is { ParsedValue: SIGNATURE signature } - && DelegateBuilder.Instance.CreateDelegateType(signature.ReturnType, signature.ParameterTypes) is { } @delegate) + && DelegateBuilder.Instance.CreateDelegateType(signature.ReturnType, signature.ParameterTypes) is NativeDelegateWrapper @delegate) { - object del = @delegate.Constructor.Invoke(new object?[] { null, funcptr }); - object res = @delegate.Invoker.Invoke(del, new object?[] { }); + + @delegate.Invoke(funcptr, ); throw new NotImplementedException(); } diff --git a/new/AutoItInterpreter/IsExternalInit.cs b/new/AutoItInterpreter/IsExternalInit.cs new file mode 100644 index 00000000..634b98b5 --- /dev/null +++ b/new/AutoItInterpreter/IsExternalInit.cs @@ -0,0 +1,9 @@ +using System.ComponentModel; +using System.Diagnostics; + +namespace System.Runtime.CompilerServices +{ + /// For C#9 record compatibility. + [EditorBrowsable(EditorBrowsableState.Never), DebuggerNonUserCode] + public sealed class IsExternalInit { } +} diff --git a/new/AutoItInterpreter/Properties/launchSettings.json b/new/AutoItInterpreter/Properties/launchSettings.json index 8b6fc0c0..bd8d7891 100644 --- a/new/AutoItInterpreter/Properties/launchSettings.json +++ b/new/AutoItInterpreter/Properties/launchSettings.json @@ -2,7 +2,8 @@ "profiles": { "AutoItInterpreter": { "commandName": "Project", - "commandLineArgs": "-tvv ../test/test" + "commandLineArgs": "-tvv ../test/test", + "nativeDebugging": true } } } \ No newline at end of file diff --git a/new/AutoItInterpreter/Runtime/DelegateBuilder.cs b/new/AutoItInterpreter/Runtime/DelegateBuilder.cs index d9c8bdcf..ded4d221 100644 --- a/new/AutoItInterpreter/Runtime/DelegateBuilder.cs +++ b/new/AutoItInterpreter/Runtime/DelegateBuilder.cs @@ -7,6 +7,9 @@ using Unknown6656.AutoIt3.Parser.DLLStructParser; using Unknown6656.Common; +using System.Net.Http.Headers; +using System.Runtime.CompilerServices; +using Unknown6656.AutoIt3.Runtime.Native; namespace Unknown6656.AutoIt3.Runtime { @@ -23,35 +26,33 @@ public sealed class DelegateBuilder private DelegateBuilder() { - _assembly = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(nameof(DelegateBuilder)), AssemblyBuilderAccess.RunAndCollect); + _assembly = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(GetRandomName()), AssemblyBuilderAccess.RunAndCollect); _module = _assembly.DefineDynamicModule(nameof(DelegateBuilder)); } - public (Type Type, ConstructorInfo Constructor, MethodInfo Invoker)? CreateDelegateType(ANNOTATED_TYPE return_type, params TYPE[] parameters) + public NativeDelegateWrapper? CreateDelegateType(ANNOTATED_TYPE return_type, params TYPE[] parameters) { try { - TypeBuilder delegate_builder = _module.DefineType(Guid.NewGuid().ToString("N"), TypeAttributes.Sealed | TypeAttributes.Public, typeof(MulticastDelegate)); + TypeBuilder delegate_builder = _module.DefineType(GetRandomName(), TypeAttributes.Sealed | TypeAttributes.Public, typeof(MulticastDelegate)); + CallingConvention callconv = return_type.CallConvention.IsFastcall ? CallingConvention.FastCall : + return_type.CallConvention.IsStdcall ? CallingConvention.StdCall : + return_type.CallConvention.IsThiscall ? CallingConvention.ThisCall : + return_type.CallConvention.IsWinAPI ? CallingConvention.Winapi : CallingConvention.Cdecl; delegate_builder.SetCustomAttribute(new CustomAttributeBuilder( typeof(UnmanagedFunctionPointerAttribute).GetConstructor(new[] { typeof(CallingConvention) })!, - new object[] - { - return_type.CallConvention.IsFastcall ? CallingConvention.FastCall : - return_type.CallConvention.IsStdcall ? CallingConvention.StdCall : - return_type.CallConvention.IsThiscall ? CallingConvention.ThisCall : - return_type.CallConvention.IsWinAPI ? CallingConvention.Winapi : CallingConvention.Cdecl - } + new object[] { callconv } )); - + ConstructorBuilder constructor = delegate_builder.DefineConstructor( MethodAttributes.RTSpecialName | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Public, CallingConventions.Standard, new[] { typeof(object), typeof(nint) } ); constructor.SetImplementationFlags(MethodImplAttributes.CodeTypeMask); - constructor.DefineParameter(1, ParameterAttributes.None, "object"); - constructor.DefineParameter(2, ParameterAttributes.None, "method"); + // constructor.DefineParameter(1, ParameterAttributes.None, "object"); + // constructor.DefineParameter(2, ParameterAttributes.None, "method"); Type?[] @params = parameters.ToArray(t => ConvertType(t, true)); @@ -60,16 +61,30 @@ private DelegateBuilder() MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.Public, CallingConventions.Standard, ConvertType(return_type.Type, false), - @params! + null, + new[] { + callconv switch + { + CallingConvention.Cdecl => typeof(CallConvCdecl), + CallingConvention.StdCall => typeof(CallConvStdcall), + CallingConvention.ThisCall => typeof(CallConvThiscall), + CallingConvention.FastCall => typeof(CallConvFastcall), + CallingConvention.Winapi when NativeInterop.OperatingSystem == OS.Windows => typeof(CallConvStdcall), + _ => typeof(CallConvCdecl), + } + }, + @params!, + null, + null ); - // invoke.SetImplementationFlags(MethodImplAttributes.CodeTypeMask); + invoke.SetImplementationFlags(MethodImplAttributes.CodeTypeMask); ParameterBuilder ProcessParameter(int index, TYPE type) { ParameterAttributes attr = index is 0 ? ParameterAttributes.Retval : ParameterAttributes.None; - // if (type.IsWSTR || type.IsSTR) - // attr |= ParameterAttributes.HasFieldMarshal; + //if (type.IsWSTR || type.IsSTR) + // attr |= ParameterAttributes.HasFieldMarshal; ParameterBuilder parameter = invoke.DefineParameter(index, attr, index is 0 ? null : "item" + index); @@ -94,17 +109,12 @@ ParameterBuilder ProcessParameter(int index, TYPE type) type.GetMethod(invoke.Name) is MethodInfo inv && type.GetConstructor(new[] { typeof(object), typeof(nint) }) is ConstructorInfo ctor) { + // new Lokad.ILPack.AssemblyGenerator().GenerateAssembly(_assembly, GetRandomName("__test", ".dll")); - - new Lokad.ILPack.AssemblyGenerator().GenerateAssembly(_assembly, $"__test{Guid.NewGuid():N}.dll"); - - - return (type, ctor, inv); - - + return new NativeDelegateWrapper(type, ctor, inv); } } - catch + catch (Exception ex) { } @@ -177,5 +187,44 @@ ParameterBuilder ProcessParameter(int index, TYPE type) return null; // TODO } + + private static string GetRandomName(string prefix = "", string suffix = "") => prefix + Guid.NewGuid() + suffix; + } + + public unsafe record NativeDelegateWrapper(Type Type, ConstructorInfo Constructor, MethodInfo Invoker) + { + private static readonly FieldInfo _methodPtr = typeof(Delegate).GetField(nameof(_methodPtr), BindingFlags.NonPublic | BindingFlags.Instance)!; + private static readonly FieldInfo _methodPtrAux = typeof(Delegate).GetField(nameof(_methodPtrAux), BindingFlags.NonPublic | BindingFlags.Instance)!; + private static readonly delegate* pdummy = &DummyMethod; + private static readonly object _mutex = new object(); + + + public object? Invoke(void* funcptr, params object?[] arguments) => Invoke((nint)funcptr, arguments); + + public object? Invoke(nint funcptr, params object?[] arguments) + { + object @delegate = Constructor.Invoke(new object?[] { null, (nint)pdummy }); + object? result; + + lock (_mutex) + try + { + _methodPtr.SetValue(@delegate, funcptr); + _methodPtrAux.SetValue(@delegate, funcptr); + + result = Invoker.Invoke(@delegate, arguments); + } + finally + { + _methodPtr.SetValue(@delegate, (nint)pdummy); + _methodPtrAux.SetValue(@delegate, (nint)pdummy); + } + + return result; + } + + private static void DummyMethod() + { + } } } diff --git a/new/AutoItInterpreter/version.txt b/new/AutoItInterpreter/version.txt index 97acd8a2..2fe5f7a3 100644 --- a/new/AutoItInterpreter/version.txt +++ b/new/AutoItInterpreter/version.txt @@ -1,2 +1,2 @@ -0.6.1303.7331 -7a77da24ffb83f015e215bf2a17c4d03c3336e15 \ No newline at end of file +0.6.1321.7332 +f99805ac759f04bfb201af9df4451b4f2f964292 \ No newline at end of file diff --git a/new/test/test.au3 b/new/test/test.au3 index d18b2fed..2aa2da24 100644 --- a/new/test/test.au3 +++ b/new/test/test.au3 @@ -1,7 +1,7 @@ -ConsoleWrite(DllCall("user32.dll", "int", "MessageBoxW", "int", 0, "wstr", "top kek", "wstr", "title", "uint", 0)) +; ConsoleWrite(DllCall("user32.dll", "int", "MessageBoxW", "int", 0, "wstr", "top kek", "wstr", "title", "uint", 0)) +ConsoleWrite(DllCall("user32.dll", "bool", "SetCursorPos", "int", 0, "int", 0)) exit ClipPut('top " kek | jej ') ConsoleWrite(@OSVersion) - diff --git a/new/util/AutoIt3.Common/ExternalServices.cs b/new/util/AutoIt3.Common/ExternalServices.cs index 31170da0..35f4b91c 100644 --- a/new/util/AutoIt3.Common/ExternalServices.cs +++ b/new/util/AutoIt3.Common/ExternalServices.cs @@ -1,6 +1,5 @@ -using System.Runtime.InteropServices.ComTypes; -using System.Runtime.InteropServices; -using System.Collections.Generic; +//#define USE_VS_DEBUGGER + using System.Threading.Tasks; using System.Diagnostics; using System.IO.Pipes; @@ -10,10 +9,15 @@ using System; using Unknown6656.AutoIt3.Localization; +#if USE_VS_DEBUGGER +using System.Runtime.InteropServices.ComTypes; +using System.Runtime.InteropServices; +using System.Collections.Generic; using EnvDTE; using DTEProcess = EnvDTE.Process; +#endif using Process = System.Diagnostics.Process; namespace Unknown6656.AutoIt3.Runtime.ExternalServices @@ -216,7 +220,7 @@ protected ExternalServiceConnector(FileInfo server, bool use_dotnet, IDebugPrint DataWriter = new BinaryWriter(_pipe_odata); DebugPrint("debug.external.started", server.FullName, name_odata, name_idata, name_debug, ServerProcess.Id); -#if DEBUG +#if USE_VS_DEBUGGER if (System.Diagnostics.Debugger.IsAttached && Environment.OSVersion.Platform is PlatformID.Win32NT) AttachVSDebugger(); #endif @@ -228,7 +232,7 @@ protected ExternalServiceConnector(FileInfo server, bool use_dotnet, IDebugPrint } ~ExternalServiceConnector() => Dispose(false); -#if DEBUG +#if USE_VS_DEBUGGER private void AttachVSDebugger() { using Process vs_current = Process.GetCurrentProcess(); @@ -354,7 +358,7 @@ private static void Try(Action a) } } -#if DEBUG +#if USE_VS_DEBUGGER public static class VisualStudioAttacher { private const string DEVENV_NAME = "devenv";