This documentation is archived and is not being maintained.

PInvoke declarations should be portable







Breaking Change


This rule is evaluates the size of each parameter and the return value of a P/Invoke and verifies that their size when marshaled to unmanaged code on 32-bit and 64-bit platforms is correct. The most common violation of this rule is to pass a fixed-sized integer where a platform-dependent pointer-sized variable is required.

This rule fires on either of the following scenarios:

  • The return value or parameter is typed as a fixed-size integer when it should be typed as an IntPtr.

  • The return value or parameter is typed as an IntPtr when it should be typed as a fixed-size integer.

You can fix this violation by using IntPtr or UIntPtr to represent handles instead of Int32 or UInt32.

You should not exclude this rule.

The following example demonstrates a violation of this rule.

internal class NativeMethods
    [DllImport("shell32.dll", CharSet=CharSet.Auto)]
    internal static extern IntPtr ExtractIcon(IntPtr hInst, 
        string lpszExeFileName, IntPtr nIconIndex);

In this example, the nIconIndex parameter is declared as a IntPtr, which is 4 bytes wide on a 32-bit platform and 8 bytes wide on a 64-bit platform. In the unmanaged declaration below, you can see that nIconIndex is a 4 byte unsigned integer on all platforms.

HICON ExtractIcon(HINSTANCE hInst, LPCTSTR lpszExeFileName, 
    UINT nIconIndex);

To fix the violation, change the declaration to the following:

internal class NativeMethods{
    [DllImport("shell32.dll", CharSet=CharSet.Auto)] 
    internal static extern IntPtr ExtractIcon(IntPtr hInst, 
        string lpszExeFileName, uint nIconIndex);