CA1901: P/Invoke declarations should be portable
Item | Value |
---|---|
RuleId | CA1901 |
Category | Microsoft.Portability |
Breaking change | Breaking - If the P/Invoke is visible outside the assembly. Non-breaking - If the P/Invoke is not visible outside the assembly. |
Cause
This rule 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.
Rule description
Either of the following scenarios violates this rule occurs:
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.
How to fix violations
You can fix this violation by using IntPtr
or UIntPtr
to represent handles instead of Int32
or UInt32
.
When to suppress warnings
You should not suppress this warning.
Example
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 an IntPtr
, which is 4 bytes wide on a 32-bit platform and 8 bytes wide on a 64-bit platform. In the unmanaged declaration that follows, 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);
}