Mutex + RegisterWaitForSingleObject = External exception C000070A

Пытаюсь воспользоваться функционалом RegisterWaitForSingleObject для ожидания мьютекса, но при вызове получаю External exception. Не просто "отказ в регистрировании коллбака", а именно EE.

Что я делаю не так? В сети в основном идут примеры на коллбаки к хендлам процессов, но документация утверждает, что мьютексы так же могут использоваться в этом вызове.

Попытка №1, самая простая:

const
  MutexName = 'Global\TForm20Mutex'; // префикс Local и без префикса не меняют результат.

// callback-функция
procedure WaitCallback(lpParameter: Pointer; TimerOrWaitFired: Boolean); stdcall;
begin
  Sleep(10); // сюда вызов не доходит.
end;

procedure TForm20.btn1Click(Sender: TObject);
var
  bResult: BOOL;
begin
  FMutexHandle := CreateMutex(nil, False, MutexName);
  if FMutexHandle = 0 then
    RaiseLastOSError;

  bResult:= RegisterWaitForSingleObject(FCallbackHandle, FMutexHandle,//
      WaitCallback, nil, INFINITE, //
      WT_EXECUTEONLYONCE or WT_EXECUTELONGFUNCTION); // ExternalException здесь

  if not bResult then // сюда управление не доходит.
    RaiseLastOSError;
end;

Попытка №100500, динамическая загрузка (перед этим - перекрывал статическую линковку, результат тот же).

type
  TRegisterWaitForSingleObject = function(out phNewWaitObject: THandle; hObject: THandle;
      CallBack: Pointer; Context: Pointer; dwMilliseconds: ULONG;
      dwFlags: ULONG): BOOL; stdcall;
  // вместо out param пробовал var и PHandle в качестве типа первого параметра.

var
  RegisterWaitForSingleObject: TRegisterWaitForSingleObject;

procedure TForm20.btn1Click(Sender: TObject);
var
  hKernel: THandle;
  bResult: BOOL;
begin
  hKernel:=LoadLibrary('kernel32.dll');
  if hKernel = 0 then
    RaiseLastOSError;

  RegisterWaitForSingleObject:=GetProcAddress(hKernel, 'RegisterWaitForSingleObject');
  if @RegisterWaitForSingleObject = nil then
    RaiseLastOSError;


  FMutex := TMutex.Create(nil, False, MutexName);

  FCallbackHandle := 0;
  bResult := RegisterWaitForSingleObject(FCallbackHandle, FMutex.Handle, @WaitCallback, 
      nil, 100, WT_EXECUTEONLYONCE or WT_EXECUTELONGFUNCTION); // и вот здесь ExternalException
  if not bResult then
    RaiseLastOSError;
end;

Stacktrace:

:76f3a6e2 KERNELBASE.RaiseException + 0x62
:00409b50 NotifyNonDelphiException + $1C
:778f8894 ; 
:778e4ec6 ntdll.KiUserExceptionDispatcher + 0x26
:77901855 ; 
:778a7b7c ntdll.TpSetWaitEx + 0x8c
:778a21d9 ; 
:765e7a7d KERNEL32.RegisterWaitForSingleObject + 0x3d
Unit20.TForm20.btn1Click($329DDE0)

Насколько я понимаю - это одна из самых базовых функций в WinAPI, поэтому вряд ли там будет какая-то ошибка, соответственно - это должна быть кривизна моих рук. Вот только в чем?

Дополнительная информация:
IDE: XE2 и 10.4.1, компиляция в 32бит, идентичная ошибка с идентичными стектрейсами на обеих
OS: Windows 10 Pro x64.
И под дебаггером и без - результат аналогичен.


Ответы (0 шт):