MovePInvokesToNativeMethodsClass fires on P/Invokes (ie methods marked with DllImport) that are not members of one of the following classes; NativeMethods, SafeNativeMethods or UnsafeNativeMethods.

For example, the following sample fires this warning.

[C#]

using
System;
using System.Runtime.InteropServices;

internal static class Directory
{
    // Violates MovePInvokesToNativeMethodsClass
    [DllImport("kernel32.dll"
)]
    internal static extern bool RemoveDirectory(string
name);
}

[Visual Basic]

Imports System
Imports System.Runtime.InteropServices

Public NotInheritable Class Directory

    Private Sub New()
    End Sub

    ' Violates MovePInvokesToNativeMethodsClass
   
<DllImport("kernal32.dll", CharSet:=CharSet.Auto)> _
   
Friend Shared Function RemoveDirectory(ByVal Name As String) As Boolean
   
End Function

End Class

In the above example, the RemoveDirectory P/Invoke should be moved to an appropriate class that is designed to only hold P/Invokes.

For most applications, moving P/Invokes to a new class called NativeMethods is typically enough. However, in situations where you are developing reusable libraries for use in other applications then you should also consider defining two other classes called SafeNativeMethods and UnsafeNativeMethods. Both of these classes are similar to the NativeMethods class, however, they are marked with a special attribute called SuppressUnmanagedCodeSecurityAttribute. Applying this attribute causes the runtime to avoid performing a full stack walk to make sure that all callers have the UnmanagedCode permission when calling the p/invoke methods containing within these classes. The runtime will check your library for this permission at startup, however, not the assemblies that reference it. This can greatly improve performance when calling unmanaged code and also allows code with limited permissions to call these methods.

However, using this attribute should not be taken lightly, as implemented incorrectly it can actually have serious security implications.

 

NativeMethods

As the NativeMethods class should not be marked with SuppressUnmanagedCodeAttribute, P/Invokes placed within in it, will require UnmanagedCode permission. As most applications run from the local machine and run with FullTrust, this is usually not a problem. However, if you developing reusable libraries, you should instead consider defining a SafeNativeMethods or UnsafeNativeMethods class.

The following example shows a method Interaction.Beep that wraps the MessageBeep function from user32.dll, the MessageBeep P/Invoke is placed within the NativeMethods class.

[C#]

using
System;
using
System.Runtime.InteropServices;
using System.ComponentModel;

public static class Interaction
{
   
// Callers require Unmanaged permission 
    public static void
Beep()
    {
       
// No need to demand a permission as callers of Interaction.Beep 
        // will require UnmanagedCode permission 
        if (!NativeMethods
.MessageBeep(-1))
            throw new Win32Exception
();
    }
}

internal static class NativeMethods
{
    [DllImport("user32.dll", CharSet = CharSet
.Auto)]
    [return: MarshalAs(UnmanagedType
.Bool)]
    internal static extern bool MessageBeep(int
uType);
}

[Visual Basic]

Imports System
Imports
System.Runtime.InteropServices
Imports System.ComponentModel

Public NotInheritable Class Interaction

    Private Sub New()
    End Sub

    ' Callers require Unmanaged permission
   
Public Shared Sub
Beep()

        ' No need to demand a permission as callers of Interaction.Beep 
        ' will require UnmanagedCode permission 
        If Not NativeMethods.MessageBeep(-1)
Then
           
Throw New
Win32Exception()
        End
If
    
    End Sub

End Class

Friend NotInheritable Class NativeMethods

    Private Sub New()
    End Sub

    <DllImport("user32.dll", CharSet:=CharSet.Auto)> _
    Friend Shared Function MessageBeep(ByVal uType As Integer) As <MarshalAs(UnmanagedType.Bool)>
Boolean
   
End Function

End Class 

In the example above, any assembly that calls NativeMethod.MessageBeep or Interaction.Beep will require UnmanagedCode permission.

 

SafeNativeMethods

P/Invoke methods that are safe to be exposed to any application and do not have any side effects should be placed in a class called SafeNativeMethods . No permissions need to be demanded and you do not need to pay too much attention to where they are getting called.

The following example shows a property Environment.TickCount that wraps the GetTickCount function from kernel32.dll.

[C#]

using
System;
using
System.Runtime.InteropServices;
using System.Security;

public static class Environment
{
   
// Callers do not require UnmanagedCode permission
   
public static int
TickCount
    {
       
get
       
{
           
// No need to demand a permission in place of
           
// UnmanagedCode as GetTickCount is considered
           
// a safe method
           
return SafeNativeMethods
.GetTickCount();
        }
    }
}

[SuppressUnmanagedCodeSecurityAttribute]
internal static class
SafeNativeMethods
{
    [DllImport("kernel32.dll", CharSet = CharSet.Auto, ExactSpelling = true
)]
    internal static extern int
GetTickCount();
}
   
[Visual Basic]

Imports System
Imports
System.Runtime.InteropServices
Imports System.Security

Public NotInheritable Class Environment

    Private Sub New()
    End Sub

    ' Callers do not require Unmanaged permission

    Public Shared ReadOnly Property TickCount() As Integer
       
Get
            ' No need to demand a permission in place of 
           
' UnmanagedCode as GetTickCount is considered 
           
' a safe method 
           
Return
SafeNativeMethods.GetTickCount()
        End
Get
   
End
Property

End Class

<SuppressUnmanagedCodeSecurityAttribute()> _
Friend NotInheritable Class SafeNativeMethods

    Private Sub New
()
    End Sub

    <DllImport("kernel32.dll", CharSet:=CharSet.Auto, ExactSpelling:=True)> _
    Friend Shared Function GetTickCount() As
Integer
   
End
Function

End Class

In the above example, although the assembly that defines Environment.TickCount still requires UnmanagedCode permission, any callers of it do not.

 

UnsafeNativeMethods

P/Invoke methods that are not safe to be called by anyone and can cause side effects should be placed in a class called UnsafeNativeMethods . These methods should be either stringently checked to make sure that they are not being exposed to the user inadvertently (the rule Review SuppressUnmanagedCodeSecurity usage can help with this) or should have another permission demanded in place of UnmanagedCode when using them.

The following example shows a method Cursor.Hide that wraps the ShowCursor function from user32.dll.

[C#]

using
System;
using
System.Runtime.InteropServices;
using
System.Security;
using System.Security.Permissions;

public static class Cursor
{
   
// Callers do not require UnmanagedCode permission, however,
   
// they do require UIPermissionWindow.AllWindows
   
public static void
Hide()
    {
       
// Need to demand an appropriate permission
       
// in place of UnmanagedCode permission as 
       
// ShowCursor is not considered a safe method
       
new
UIPermission(UIPermissionWindow.AllWindows).Demand();
        UnsafeNativeMethods.ShowCursor(false
);
    }
}

[SuppressUnmanagedCodeSecurityAttribute]
internal static class
UnsafeNativeMethods
{
    [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true
)]
    internal static extern int ShowCursor([MarshalAs(UnmanagedType.Bool)]bool
bShow);
}

[Visual Basic]


Imports System
Imports
System.Runtime.InteropServices
Imports
System.Security
Imports System.Security.Permissions

Public NotInheritable Class Cursor

    Private Sub New()
    End Sub

    ' Callers do not require Unmanaged permission, however, 
   
' they do require UIPermission.AllWindows
   
Public Shared Sub
Hide()

       
' Need to demand an appropriate permission 
       
' in place of UnmanagedCode permission as 
        ' ShowCursor is not considered a safe method 
        Dim permission As New
UIPermission(UIPermissionWindow.AllWindows)
        permission.Demand()

        UnsafeNativeMethods.ShowCursor(False
)

    End
Sub

End Class

<SuppressUnmanagedCodeSecurityAttribute()> _
Friend NotInheritable Class UnsafeNativeMethods

    Private Sub New()
    End Sub

    <DllImport("user32.dll", CharSet:=CharSet.Auto, ExactSpelling:=True)> _
    Friend Shared Function ShowCursor(<MarshalAs(UnmanagedType.Bool)> ByVal bShow As Boolean) As
Integer
   
End
Function

End Class

In the above example, although the assembly that defines Cursor.Hide still requires UnmanagedCode permission, any callers of it do not. In place of UnmanagedCode however, callers will require UIPermission.AllWindows.