Wraping a native library that implements a callback in C #

I have a Visual Studio 2008 C # .NET 3.5 class that provides access to a native library. The library has a Register method that allows the user to specify a callback to be triggered on some event. I have provided a C # implementation below:

internal class MyLibHandle : SafeHandleZeroOrMinusOneIsInvalid { /*...*/ }

internal static class NativeMethods
{
    public delegate void OnSomeEventDelegate (FOO foo, IntPtr user);

    [DllImport("MyLib.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.U1)]
    public static extern bool MyLib_Register(MyLibHandle handle, OnSomeEventDelegate callback, IntPtr user);
}

public class MyWrappedLib : IDisposable
{
    private MyLibHandle handle_;

    private event EventHandler<OnSomeEventArgs> some_event_int_;

    public event EventHandler<OnSomeEventArgs> SomeEvent
    {
        add
        {
            if (some_event_int_ == null)
            {
                if (!NativeMethods.MyLib_Register(handle_, ReceivedSomeEvent, IntPtr.Zero))
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }
            some_event_int_ += value;
        }
        remove
        {
            some_event_int_ -= value;
            if (some_event_int_ == null)
            {
                if (!NativeMethods.MyLib_DeRegister(handle_, -1))
                    throw new Win32Exception(Marshal.GetLastWin32Error());
            }
        }
    }

    private void ReceivedSomeEvent(FOO foo, IntPtr user)
    {
        OnSomeEvent(new OnSomeEventArgs() { foo = foo });
    }

    protected virtual void OnBeacon(OnSomeEventArgs args)
    {
        EventHandler<OnSomeEventArgs> evt = some_event_int_;
        if (evt != null)
            evt(this, args);
    }
}

      

It works, but I get a couple of ominous audio warnings

warning : CA1065 : Microsoft.Design : 'MyWrappedLib.SomeEvent.add(EventHandler<OnSomeEventArgs>)' creates an exception of type 'Win32Exception', an exception type that should not be raised in this type of method.

warning : CA2122 : Microsoft.Security : 'MyWrappedLib.SomeEvent.add(EventHandler<OnSomeEventArgs>)' calls into 'Marshal.GetLastWin32Error()' which has a LinkDemand. By making this call, 'Marshal.GetLastWin32Error()' is indirectly exposed to user code.

      

What is the recommended way to handle this situation? Should I create a method to handle event subscriptions instead of the traditional add; Delete; accessors?

thank

+3


source to share


1 answer


The following types of exceptions are allowed for event assemblers:

  • System.InvalidOperationException and all derivatives (including System.ObjectDisposedException )

  • System.NotSupportedException and all derivatives

  • ArgumentException and Derivatives

Why does native method return false? Will this be due to some external conditions, or is it the result of invalid parameters?

So, I would wrap Win32Exception internally for InvalidOperationException, or ArgumentException, depending on your situation.

The second warning (CA2122) is about security - it warns that Marshal.GetLastWin32Error is performing security checks, and your code is not. This security check is performed only once, on the first call. All calls after that are not checked for access rights, for performance reasons. Therefore, in theory, the first call can be made to a trusted user, and all further calls will not be restricted.



You either need to decorate your event handler with the following attribute:

[SecurityPermission (SecurityAction.InheritanceDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]

(it checks if the code has permission to call managed code) or suppress this warning if security is not a concern in your application.

The details are detailed in this question .

+1


source







All Articles