Mark boolean pinvoke arguments with MarshalAs
TypeName |
MarkBooleanPInvokeArgumentsWithMarshalAs |
CheckId |
CA1414 |
Category |
Microsoft.Interoperability |
Breaking Change |
Breaking |
Cause
A platform invoke method declaration includes a System.Boolean parameter or return value but the System.Runtime.InteropServices.MarshalAsAttribute attribute is not applied to the parameter or return value.
Rule Description
A platform invoke method accesses unmanaged code and is defined by using the Declare keyword in Visual Basic or the System.Runtime.InteropServices.DllImportAttribute. MarshalAsAttribute specifies the marshaling behavior used to convert data types between managed and unmanaged code. Many simple data types, such as System.Byte and System.Int32, have a single representation in unmanaged code and do not need their marshaling behavior specified; the common language runtime automatically supplies the correct behavior.
The Boolean data type has multiple representations in unmanaged code. When the MarshalAsAttribute is not specified, the default marshaling behavior for the Boolean data type is System.Runtime.InteropServices.UnmanagedType.Bool. This is a 32-bit integer, which is not appropriate in all circumstances. The Boolean representation required by the unmanaged method should be determined and matched to the appropriate System.Runtime.InteropServices.UnmanagedType. UnmanagedType.Bool is the Win32 BOOL type, which is always 4 bytes. UnmanagedType.U1 should be used for C++ bool
or other 1-byte types. For more information, see Default Marshaling for Boolean Types.
How to Fix Violations
To fix a violation of this rule, apply MarshalAsAttribute to the Boolean parameter or return value. Set the value of the attribute to the appropriate UnmanagedType.
When to Exclude Warnings
Do not exclude a warning from this rule. Even if the default marshaling behavior is appropriate, the code is more easily maintained when the behavior is explicitly specified.
Example
The following example shows two platform invoke methods marked with the appropriate MarshalAsAttribute attributes.
Imports System
Imports System.Runtime.InteropServices
<assembly: ComVisible(False)>
Namespace UsageLibrary
<ComVisible(True)> _
Class NativeMethods
Private Sub New()
End Sub
<DllImport("user32.dll", SetLastError := True)> _
Friend Shared Function MessageBeep(uType As UInt32) _
As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
<DllImport("mscoree.dll", SetLastError := True)> _
Friend Shared Function StrongNameSignatureVerificationEx( _
<MarshalAs(UnmanagedType.LPWStr)> wszFilePath As String, _
<MarshalAs(UnmanagedType.U1)> fForceVerification As Boolean, _
<MarshalAs(UnmanagedType.U1)> ByRef pfWasVerified As Boolean) _
As <MarshalAs(UnmanagedType.U1)> Boolean
End Function
End Class
End Namespace
using System;
using System.Runtime.InteropServices;
[assembly: ComVisible(false)]
namespace InteroperabilityLibrary
{
[ComVisible(true)]
internal class NativeMethods
{
private NativeMethods() {}
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern Boolean MessageBeep(UInt32 uType);
[DllImport("mscoree.dll",
CharSet = CharSet.Unicode,
SetLastError = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool StrongNameSignatureVerificationEx(
[MarshalAs(UnmanagedType.LPWStr)] string wszFilePath,
[MarshalAs(UnmanagedType.U1)] bool fForceVerification,
[MarshalAs(UnmanagedType.U1)] out bool pfWasVerified);
}
}
using namespace System;
using namespace System::Runtime::InteropServices;
[assembly: ComVisible(false)];
namespace InteroperabilityLibrary
{
[ComVisible(true)]
ref class NativeMethods
{
private:
NativeMethods() {}
internal:
[DllImport("user32.dll", SetLastError = true)]
[returnvalue: MarshalAs(UnmanagedType::Bool)]
static Boolean MessageBeep(UInt32 uType);
[DllImport("mscoree.dll",
CharSet = CharSet::Unicode,
SetLastError = true)]
[returnvalue: MarshalAs(UnmanagedType::U1)]
static bool StrongNameSignatureVerificationEx(
[MarshalAs(UnmanagedType::LPWStr)] String^ wszFilePath,
[MarshalAs(UnmanagedType::U1)] Boolean fForceVerification,
[MarshalAs(UnmanagedType::U1)] Boolean^ pfWasVerified);
};
}
Related Rules
PInvoke declarations should be portable
Specify marshaling for pinvoke string arguments
See Also
Reference
System.Runtime.InteropServices.UnmanagedType
Concepts
Default Marshaling for Boolean Types