Search code examples
c#.netvb.netwinapipinvoke

Getting unexpected CA1901 warning for ChildWindowFromPointEx function


When I use the code analysis feature in my Visual Studio project, I'm getting a unexpected CA1901 warning for ChildWindowFromPointEx and also for RealChildWindowFromPoint, at their parameters of type POINT.

I just defined a structure with name NativePoint with X and Y fields as Int32 type, which I'm using as an equivalent for those POINT parameters.

I understand what the portability means in terms of value size when running under x86 or x64, however, in this case I'm not sure how to solve this warning, because I'm using the same NativePoint structure for POINT parameters of other functions like for example: ChildWindowFromPoint, ClientToScreen, GetCursorPos and many others, and code analysis is not warning about them, and they work when running on a x86 and x64 process.

In fact, ChildWindowFromPoint and ChildWindowFromPointEx only seems to differ by one additional parameter, both takes the same POINT structure as parameter so I don't understand why ChildWindowFromPointEx is warning about portability issues while for ChildWindowFromPoint is all fine.

My question is: in C# or VB.NET, how do I properly fix (not suppress) this warning for ChildWindowFromPointEx and RealChildWindowFromPoint functions?. Maybe I need to define another different NativePoint struct with different field types only to use with these two functions?. But why these two functions throws a warning while for ChildWindowFromPoint does not if both takes the same POINT (my NativePoint) structure?.

Note that I get the same warning for those two functions if I use System.Drawing.Point structure, but only for those two.


[DllImport("user32.dll", EntryPoint="ChildWindowFromPointEx", SetLastError=false)]
public extern static IntPtr ChildWindowFromPointEx(IntPtr hwndParent,
                                              NativePoint point, 
                                                     uint flags);

[DllImport("user32.dll", EntryPoint="RealChildWindowFromPoint", SetLastError=false)]
public extern static IntPtr RealChildWindowFromPoint(IntPtr hwndParent, 
                                                NativePoint point);

[StructLayout(LayoutKind.Sequential)]
public struct NativePoint {
    public int X;
    public int Y;
}

Solution

  • After poking around in the responsible analysis assembly, there is a mismatch between the Windows API documentation and the data set used by the analysis plugin.

    The rule thinks RealChildWindowFromPoint should have have 3 parameters of each 4 bytes, and ChildWindowFromPointEx 4 parameters of each 4 bytes on x86. ChildWindowFromPoint on the other hand is listed as having one 4 byte parameter and one 8 byte parameter as expected.

    Indeed, declaring RealChildWindowFromPoint this way seems to satisfy the code analysis, but I don't know enough about the Windows API calling conventions to say whether this is actually a valid way of calling that method:

    [DllImport("user32.dll", EntryPoint = "RealChildWindowFromPoint", SetLastError = false)]
    public static extern IntPtr RealChildWindowFromPoint(IntPtr hwndParent, int x, int y);
    

    Considering that rules for RealChildWindowFromPoint and ChildWindowFromPointEx are missing data for the return value size as well as x64 declarations, while the data for ChildWindowFromPoint is complete, I would assume that this is simply a mistake in the data rather than an intentional recommendation.