Странная проблема P/Invoke на Win 7 x64

Я P/Invoking для CreateRectRgn в gdi32.dll. Обычная подпись P/Invoke для этой функции:

[DllImport("gdi32", SetLastError=true)]
static extern IntPtr CreateRectRgn(int nLeft, int nTop, int nRight, int nBottom);

В качестве ярлыка я также определил эту перегрузку:

[DllImport("gdi32", SetLastError=true)]
static extern IntPtr CreateRectRgn(RECT rc);

[StructLayout(LayoutKind.Sequential)]
struct RECT{
    public int left;
    public int top;
    public int right;
    public int bottom;
}

(Да, я в курсе CreateRectRgnIndirect, но так как я должен использовать функции для преобразования между System.Drawing.Rectangle и это RECT структура, выше, более полезна для меня, поскольку она не включает промежуточную переменную.)

Эта перегрузка должна работать идентично обычной сигнатуре, так как она должна поместить стек в идентичное состояние при входе в CreateRectRgn, И действительно, на Windows XP 32-битная работает без нареканий. Но в Windows 7 64-битная функция возвращает ноль, и Marshal.GetLastWin32Error() возвращает 87, что означает "Неверный параметр".

Любые идеи относительно того, в чем может быть проблема?

1 ответ

Решение

Ой. Соглашение о вызовах, которое Microsoft использует на x64, полностью отличается от STDCALL. В призыве к CreateRectRgnстек вообще не используется для параметров, все они передаются в регистрах. Когда я пытаюсь передать RECT структура, она делает копию структуры в стеке и помещает указатель на эту копию в регистр. Поэтому этот маленький трюк не будет работать вообще в 64-битной Windows. Теперь мне нужно пройти через весь код взаимодействия, найти другие места, где я это сделал, и вытащить их все.

Другие вопросы по тегам