Korzystam z mechanizmu PInvoke, w tym celu napisałem prostą klasę dziedziczącą po SafeHandle:

using Microsoft.Win32.SafeHandles;
using System.Security;

namespace Hermeslogger.Core
{
    internal sealed class SafeWinEventHookHandle : SafeHandleZeroOrMinusOneIsInvalid
    {
        public SafeWinEventHookHandle() : base(true)
        {
        }

        [SecurityCritical]
        protected override bool ReleaseHandle()
        {
            return NativeMethods.UnhookWinEvent(this.handle);
        }
    }
}

Tutaj moja definicja PInvoke:

using System;
using System.Runtime.InteropServices;
using System.Text;

namespace Hermeslogger.Core
{
    internal delegate void WinEventProcDef(SafeWinEventHookHandle winEventHook, int eventId, IntPtr windowHandle, int objectId, int childId, int eventThread, int eventTime);

    internal static class NativeMethods
    {
        public const int EVENT_OBJECT_FOCUS = 0x8005;
        public const int EVENT_SYSTEM_FOREGROUND = 0x0003;
        public const int WINEVENT_OUTOFCONTEXT = 0x0000;
        public const int WM_DESTROY = 0x0002;

        [DllImport(ExternDll.User32, CharSet = CharSet.Auto)]
        public static extern IntPtr GetForegroundWindow();

        [DllImport(ExternDll.User32, CharSet = CharSet.Auto)]
        public static extern int GetWindowText(HandleRef windowHandle, StringBuilder text, int maxLength);

        [DllImport(ExternDll.User32, CharSet = CharSet.Auto)]
        public static extern int GetWindowTextLength(HandleRef windowHandle);

        [DllImport(ExternDll.User32, CharSet = CharSet.Auto)]
        public static extern IntPtr SendMessage(IntPtr window, int message, IntPtr wParam, IntPtr lParam);

        [DllImport(ExternDll.User32)]
        public static extern SafeWinEventHookHandle SetWinEventHook(int eventMin, int eventMax, IntPtr instance, WinEventProcDef winEventProc, uint processId, uint threadId, int flags);

        [DllImport(ExternDll.User32)]
        public static extern bool UnhookWinEvent(IntPtr winEventHook);
    }
}

Teraz podczas wykonania kodu:

            NativeMethods.SetWinEventHook(NativeMethods.EVENT_OBJECT_FOCUS, NativeMethods.EVENT_OBJECT_FOCUS, IntPtr.Zero, this.winEventProc, 0, 0, NativeMethods.WINEVENT_OUTOFCONTEXT);
            NativeMethods.SetWinEventHook(NativeMethods.EVENT_SYSTEM_FOREGROUND, NativeMethods.EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, this.winEventProc, 0, 0, NativeMethods.WINEVENT_OUTOFCONTEXT);
 

Otrzymuje wyjątek:
Cannot marshal 'parameter #1': SafeHandles cannot be marshaled from unmanaged to managed.

Czy przyczyna leży w złej deklaracji mojego SafeHandle? Czy może gdzieś indziej