私は制御できないホストから呼び出されるDLLにプラグインコードを書いています。Visual Studioでカスタムプロローグとエピローグコードを使用してネイキッド関数を記述する
ホストは、プラグインが__stdcall関数としてエクスポートされることを前提としています。ホストには、関数の名前と引数の詳細が渡され、LoadLibrary、GetProcAddressを介して動的に呼び出され、手動で引数をスタックにプッシュします。
通常、プラグインDLLは一定のインターフェイスを公開します。私のプラグインは、dllロード時に設定されたインターフェースを公開しています。これを達成するために、私のプラグインは、dllがコンパイルされた時点で定義されている標準エントリーポイントのセットを公開し、必要に応じて公開されている内部機能にそれらを割り当てます。
それぞれの内部関数は異なる引数をとることがありますが、これは物理的なエントリポイント名と共にホストに伝えられます。私の物理的なdllエントリーポイントはすべて、単一のvoid *ポインターを取るように定義されています。そして、最初の引数からのオフセットとホストに伝達された既知の引数リストから作業することによって、スタックから後続のパラメーターをマーシャリングします。
ホストは、正しい引数でプラグインの関数を正常に呼び出すことができ、すべて正常に動作します...しかし、私の知っている機能は、それらは4バイトのポインタを取る__stdcall関数として定義されているので、呼び出し側がもっと多くの引数をスタックにプッシュしても、常に最後に 'ret 4'を返します。 b)私は、ret 4が返されたスタックの4バイトをあまりにも多くポップするので、引数を取らない関数を扱うことはできません。
私のプラグインをホストの呼び出しコードに追いかけると、実際にはa)大きな問題ではないことが分かります。ホストはディスパッチコールから戻るまでいくらかのスタックスペースを失います。その時点で、スタックフレームがクリーンアップされ、私のゴミはきれいになります。しかし...
__cdeclに切り替えて、まったくクリーンアップしないで、b)を解決できます。私は裸の関数に切り替えて、自分の一般的な引数をクリーンアップコードを書くことによって)私は解決することができると仮定します。
私はちょうど私がそれはのような単純なものであろうと期待していたと呼ばれていた機能で使用される引数のスペースの量を知っているので:
extern "C" __declspec(naked) __declspec(dllexport) void * __stdcall EntryPoint(void *pArg1)
{
size_t argumentSpaceUsed;
{
void *pX = RealEntryPoint(
reinterpret_cast<ULONG_PTR>(&pArg1),
argumentSpaceUsed);
__asm
{
mov eax, dword ptr pX
}
}
__asm
{
ret argumentSpaceUsed
}
}
しかし、RETは、コンパイル時間が必要としてそれが動作しませんが定数...任意の提案?
更新日:私は仕事に思われる、これに持っているロブ・ケネディの提案に
おかげで...
extern "C" __declspec(naked) __declspec(dllexport) void * __stdcall EntryPoint(void *pArg1)
{
__asm {
push ebp // Set up our stack frame
mov ebp, esp
mov eax, 0x0 // Space for called func to return arg space used, init to 0
push eax // Set up stack for call to real Entry point
push esp
lea eax, pArg1
push eax
call RealEntryPoint // result is left in eax, we leave it there for our caller....
pop ecx
mov esp,ebp // remove our stack frame
pop ebp
pop edx // return address off
add esp, ecx // remove 'x' bytes of caller args
push edx // return address back on
ret
}
}
が、これは右見ていますか?
これは決して使用されていないので個人的にフレームポインタを気にすることはありませんが、それ以外の解決策はうまくいきます。 –
元々は、argsスペースと戻り値のスペースをフレームポインタから索引付けしていましたが、eaxの戻り値を移動してから戻ってしまいました。フレームポインタの必要性がなくなったと思います。私はそれを取り除くべきだと思う...助けてくれてありがとう。 –