Skip to content

Commit

Permalink
Continued implementing DllCall (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
Unknown6656 committed Jul 29, 2020
1 parent f99805a commit e2bc3ed
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 50 deletions.
12 changes: 6 additions & 6 deletions new/AutoItInterpreter/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -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")]
Expand All @@ -35,11 +35,11 @@ public static class __module__
/// <summary>
/// The interpreter's current version.
/// </summary>
public static Version? InterpreterVersion { get; } = Version.Parse("0.6.1303.7331");
public static Version? InterpreterVersion { get; } = Version.Parse("0.6.1321.7332");
/// <summary>
/// The Git hash associated with the current build.
/// </summary>
public const string GitHash = "7a77da24ffb83f015e215bf2a17c4d03c3336e15";
public const string GitHash = "f99805ac759f04bfb201af9df4451b4f2f964292";
/// <summary>
/// The URL of this project's Git(Hub) repository.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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<SIGNATURE>? 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();
}
Expand Down
9 changes: 9 additions & 0 deletions new/AutoItInterpreter/IsExternalInit.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.ComponentModel;
using System.Diagnostics;

namespace System.Runtime.CompilerServices
{
/// <summary>For C#9 record compatibility.</summary>
[EditorBrowsable(EditorBrowsableState.Never), DebuggerNonUserCode]
public sealed class IsExternalInit { }
}
3 changes: 2 additions & 1 deletion new/AutoItInterpreter/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"profiles": {
"AutoItInterpreter": {
"commandName": "Project",
"commandLineArgs": "-tvv ../test/test"
"commandLineArgs": "-tvv ../test/test",
"nativeDebugging": true
}
}
}
99 changes: 74 additions & 25 deletions new/AutoItInterpreter/Runtime/DelegateBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -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));

Expand All @@ -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);

Expand All @@ -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)
{
}

Expand Down Expand Up @@ -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*<void> 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()
{
}
}
}
4 changes: 2 additions & 2 deletions new/AutoItInterpreter/version.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
0.6.1303.7331
7a77da24ffb83f015e215bf2a17c4d03c3336e15
0.6.1321.7332
f99805ac759f04bfb201af9df4451b4f2f964292
4 changes: 2 additions & 2 deletions new/test/test.au3
Original file line number Diff line number Diff line change
@@ -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)

16 changes: 10 additions & 6 deletions new/util/AutoIt3.Common/ExternalServices.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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();
Expand Down Expand Up @@ -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";
Expand Down

0 comments on commit e2bc3ed

Please sign in to comment.