Code Access Security in action – calling Unmanaged Code

The following is an example of how code access security might affect your code when calling unmanaged code. Unmanaged code is a posh way of saying “It isn’t .NET code, it is the stuff you used to write before .NET” :-)

In VB6 making a call to a Windows API function wasn't affected by any security settings. Potentially in .NET, an administrator might configure a machine's code access security policy to disallow calls to unmanaged code (such as the Windows API), because this is seen as a security risk. That means that code like this, could fail with a SecurityException, when the API function is invoked:

    1:  Module Module1
    2:      Sub Main()
    3:          Win32.MessageBox(0, "Here's a MessageBox", "Platform Invoke Sample", 0)
    4:      End Sub
    5:  End Module
    7:  Public Class Win32
    8:      Declare Auto Function MessageBox Lib "user32.dll" ( _
    9:          ByVal hWnd As Integer, ByVal txt As String, _
   10:          ByVal caption As String, ByVal Type As Integer) _
   11:          As Integer
   12:  End Class

There's nothing you can do to stop the code failing (other than having a word with the administrator), but you can handle things a bit more gracefully. You can check when your app starts up whether you've got all the permissions you want, and then handle the situation before you hit the problem. This can be done with an attribute (declaratively), so the permissions are checked when an assembly is loaded:

<Assembly:SecurityPermissionAttribute(SecurityAction.Demand, Flags := SecurityPermissionFlag.UnmanagedCode)>

You could also perform the check programmatically:

    1:  Try
    2:          Dim sp As New SecurityPermission(SecurityPermissionFlag.UnmanagedCode)
    3:          Console.WriteLine("Demanding SecurityPermissionFlag.UnmanagedCode")
    4:          sp.Demand()
    5:          Console.WriteLine("Demand for SecurityPermissionFlag.UnmanagedCode succeeded.")
    6:          Catch e As Exception
    7:              Console.WriteLine(("Demand for SecurityPermissionFlag.UnmanagedCode failed: " & e.Message))
    8:  End Try

Either way you can test for the permission before you need to use it.

The above checks whether you had the necessary permissions to perform an operation (in this case calling unmanaged code) by using Demand. You can also Assert or Deny a permission.

- SecurityAction.Demand What in fact you're doing here is checking that your assembly has the requested permission, and that any assemblies above you in the call-stack also have that permission.

This is a little bit different. You're still checking that your assembly has the requested permission, but you're also saying to the CLR - "Don't bother about checking further up the call stack". In effect, you are taking full responsibility for security. This is usually seen as dangerous behaviour, but there are some circumstances where it's useful.
  • SecurityAction.Deny
    Here you're saying you don't want a permission. Not at first sight much use, because if you don't want to be able to do something, then you won't write any code to try and do it! However, this also switches off the permission for any assemblies that you call (that might have been written by someone else), unless of course they go ahead and do an Assert!