Почему при статической линковке DLL к консольной программе на Delphi исключения вызывают ошибки access violation?

Пытаюсь подключить к Delphi стандартный виндовый компонент amsi.dll (проверка области памяти антивирусом). Все работает, включая успешное определение зараженных файлов, но при возникновении исключений (создаваемых вручную с помощью raise) возникают ошибки доступа к памяти - Access violation или Stack Overflow. Подозреваю, что импортированные из DLL функции объявляются или вызываются неправильно, из-за чего портится стек, но не могу понять, в чем именно проблема.

Минимальный код, продуцирующий ошибку, ниже. Если закомментировать проблемный блок, ошибка исчезает.

program Project1;
{$APPTYPE CONSOLE}

uses SysUtils, Classes, Windows, comobj;

type
  HAMSICONTEXT__ = record
    unused: Integer;
  end;

  PHAMSICONTEXT__ = ^HAMSICONTEXT__;
  HAMSICONTEXT = PHAMSICONTEXT__;
  PHAMSICONTEXT = ^HAMSICONTEXT;

var
  AmsiContext: HAMSICONTEXT;
  fResult: HRESULT;
  appName: WideString = 'amsitest';

function AmsiInitialize(appName: LPCWSTR; amsiContext: PHAMSICONTEXT): HRESULT; cdecl;
  external 'amsi.dll' name 'AmsiInitialize';

procedure AmsiUninitialize(amsiContext: HAMSICONTEXT); cdecl;
  external 'amsi.dll' name 'AmsiUninitialize';

begin
  try
    CoInitializeEx(nil, 0);
    //problematic block start
    if(AmsiInitialize(PWideChar(appName), @AmsiContext) <> S_OK)
      then Raise(Exception.Create('AmsiInitialize failed'));
    AmsiUninitialize(AmsiContext);
    //problematic code end
    Raise(Exception.Create('generic error'));
  except
    on E:Exception do writeln(E.Message);
  end;
end.


Объявление соответствующих структур и функций в amsi.h выглядит так. Заголовочный файл amsi.h был конвертирован в Delphi с помощью утилиты Chet.
DECLARE_HANDLE(HAMSICONTEXT);
DECLARE_HANDLE(HAMSISESSION);

STDAPI AmsiInitialize(
    _In_  LPCWSTR appName,
    _Outptr_ HAMSICONTEXT* amsiContext);

STDAPI_(VOID) AmsiUninitialize(
    _In_  HAMSICONTEXT amsiContext);


Прошу помощи знатоков в решении проблемы.
  • Вопрос задан
  • 34 просмотра
Решения вопроса 1
Vapaamies
@Vapaamies
Психанул и снес свои ответы козлам, не отмечающим…
STDAPI AmsiInitialize(
    _In_  LPCWSTR appName,
    _Outptr_ HAMSICONTEXT* amsiContext);

В Delphi это разве не stdcall будет?
DECLARE_HANDLE(HAMSICONTEXT);
DECLARE_HANDLE(HAMSISESSION);

По-хорошему нужно бы узнать, как объявлена DECLARE_HANDLE, но с высокой вероятностью на Delphi это объявление должно идти так:
type
  HAMSICONTEXT = type THandle;
  HAMSISESSION = type THandle;

Если я прав, последующие объявления типов не нужны — это чисто сишные заморочки. В Delphi возвращаемый описатель логично объявить через var:
function AmsiInitialize(appName: LPCWSTR; var amsiContext: HAMSICONTEXT): HRESULT; stdcall;
  external 'amsi.dll' name 'AmsiInitialize';
procedure AmsiUninitialize(amsiContext: HAMSICONTEXT); stdcall;
  external 'amsi.dll' name 'AmsiUninitialize';
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы