wallstudio/RecottePlugin

.NETライブラリに対応

Opened this issue · 10 comments

RecottePluginManagerに.NETのホストをさせて、NativeDLLと一緒にManagedDLLも呼び出すようにする

https://github.com/dotnet/samples/tree/main/core/hosting

image

DLLMainから呼ぶと、WaitForSingleObjectが帰ってこない…

スタックトレース自体wmainから呼んだ時と同じ(こっちはsyscallが即時帰ってくる)

00007FF879F6CDD8 0F 1F 84 00 00 00 00 00 nop         dword ptr [rax+rax]  
00007FF879F6CDE0 4C 8B D1             mov         r10,rcx  
00007FF879F6CDE3 B8 04 00 00 00       mov         eax,4  
00007FF879F6CDE8 F6 04 25 08 03 FE 7F 01 test        byte ptr [7FFE0308h],1  
00007FF879F6CDF0 75 03                jne         NtWaitForSingleObject+15h (07FF879F6CDF5h)  
00007FF879F6CDF2 0F 05                syscall  
00007FF879F6CDF4 C3                   ret  

WinMainの呼出し部分に遅延させた(もちろんうまくいく)

28b4daf#diff-01f5f0a4a10786db073a26a3680f98c83f1f39069fbf6b31266334a26e99dc73R353

どの道、DllMainが使えないならC++/CLIで良いのでは?ということで

以下の手順でC++/CLI化は可能。(DLLProxyもちゃんと動いてる)
ただし、C++17までなので、std::format や PluginHelper が使えない…

image

image

C++/CLIでビルドすると、Ijwhost.dll が生成されてしまう。この補助DLLがないと実行時エラーになるが、本体のDLLに以下の関数をExportさせるとIjwhost.dll消してもでも動く。
(ロード時に本体以外のDLLが必要だと、Recotte本体ディレクトリに d3d11.dll のリンク以外を置かないといけないのはどうしても避けたい)

// https://docs.microsoft.com/ja-jp/dotnet/framework/unmanaged-api/hosting/cordllmain-function
extern "C" __declspec(dllexport) BOOL STDMETHODCALLTYPE _CorDllMain(HINSTANCE hInst, DWORD fdwReason, LPVOID lpReserved)

RecottePluginManager_NET.zip

Ijwhostに関する情報

ただ、結局のところ、ijwhostを消せたところで、.NETRuntime本体を同梱できているわけではない、シングルファイルはあきらめるべき…🤔(最悪でもRecotteディレクトには d3d11.dll 以外置きたくないという要件はどちらでも満たせる)

究極的にはこれができればうれしい

REM https://github.com/wallstudio/WindowsExeHackSample/blob/master/Synthesize/Extract/build.bat
dotnet publish ^
    --output .. ^
    --runtime win-x64 ^
    --self-contained=true ^
    -p:Configuration=Release ^
    /p:PublishSingleFile=true ^
    /p:IncludeNativeLibrariesForSelfExtract=true ^
    /p:DebugType=None ^
    /p:DebugSymbols=false ^

https://github.com/dotnet/designs/blob/main/accepted/2020/single-file/design.md

単一ファイルにかんする調査

https://qiita.com/up-hash/items/39fa0671bf390147eca9

余計なDLLを作らないようにするには、Runtimeを魔改造&リンクしてビルドするか、Resourceとして持ってPELoaderを実装するしかなさそう

いつかやってみたいのはあるけど、今回はそこまでするのはやめておこう

https://snoozy.hatenablog.com/entry/2020/01/20/033114

RecottePlugin
  ├ PluginManager
  │   ├ ManagedLoader.dll (managed)
  │   ├ PluginManager.dll (native)
  │   │
  │   ├ hostfxr.dll  (native; dotnet runtime)
  │   ├ coreclr.dll  (native; dotnet runtime)
  │   ├ clrjit.dll  (native; dotnet runtime)
  │   ├ clrcompression.dll (native; dotnet runtime)
  │   └ stdibs (managed; dotnet runtime)
  │       ├ mscorlib.dll
  │       ├ System.Core.dll
  │       └ ...
  ├ PluginX
...

https://github.com/dotnet/runtime/blob/v6.0.0/docs/project/dotnet-filenames.md