CA1404 - although the sentence is preceded by a return clause, CA2000 - despite the absence of further use of references

I would like to understand why two CA warnings appear in my code:

CA2000 Disposal of objects before loss of visibility In the method 'ImpersonateValidUser (string, string, string, LogOnType, LogOnProvider, ImpersonationLevel)', System.IDisposable.Dispose is called on the 'tempWindowsIdentity' object before all references to it are outside the scope.

CA1404 A GetLastError call immediately after the P / Invoke Method 'ImpersonateValidUser (string, string, string, LogOnType, LogOnProvider, ImpersonationLevel)' called GetLastWin32Error, but the immediately preceding call to 'IDisposable.Dispose ()' is not a P / Invoke expression. Move the call to GetLastWin32Error so that it immediately follows the call to the appropriate platform.

The following is a simplified code example with lines commented out exactly at the location of the warnings:

private static void Impersonate(string userName, string domain, string password, LogOnType logonType, LogOnProvider logonProvider, ImpersonationLevel impersonationLevel)
{
    var token = IntPtr.Zero;
    var tokenDuplicate = IntPtr.Zero;
    if (NativeMethods.RevertToSelf())
    {
        if (NativeMethods.LogonUser(userName, domain, password, (int)logonType, (int)logonProvider, ref token) != 0)
        {
            if (NativeMethods.DuplicateToken(token, (int)impersonationLevel, ref tokenDuplicate) != 0)
            {
                /* CA2000 */ using (var tempWindowsIdentity = new WindowsIdentity(tokenDuplicate))
                {
                    _impersonationContext = tempWindowsIdentity.Impersonate();
                    return;
                }
            }
        }
    }
    /* CA1404 */ var e = Marshal.GetLastWin32Error();
    throw new Win32Exception(e);
}

CA2000 - the object is tempWindowsIdentitynot used after the instruction completes using(), so why is this a warning?

CA1404 - Marshal.GetLastWin32Error() . using() , return, Marshal.GetLastWin32Error() , ?

+5
3

CA... ... Code Analysis .

private static void Impersonate(string userName, string domain, string password, LogOnType logonType, LogOnProvider logonProvider, ImpersonationLevel impersonationLevel)
{
    if (!NativeMethods.RevertToSelf())
        throw new Win32Exception(Marshal.GetLastWin32Error());

    IntPtr token = IntPtr.Zero;

    if (NativeMethods.LogonUser(userName, domain, password, (int)logonType, (int)logonProvider, ref token) == 0)
        throw new Win32Exception(Marshal.GetLastWin32Error());

    IntPtr tokenDuplicate = IntPtr.Zero;

    if (NativeMethods.DuplicateToken(token, (int)impersonationLevel, ref tokenDuplicate) == 0)
        throw new Win32Exception(Marshal.GetLastWin32Error());

WindowsIdentity tempWindowsIdentity;

    try
    {
        tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
        _impersonationContext = tempWindowsIdentity.Impersonate();
    }
    finally
    {
        if (tempPort != null)
        {
            tempWindowsIdentity.Dispose();
            tempWindowsIdentity = null;
        }
    }
}

CA1404, , API, , , , . CA2000 WindowsIdentity , , ; , .

0

, CA2000 , , , using;

, try/finally .

CA1404 , Marshal.GetLastWin32Error(); . Marshal.GetLastWin32Error(); if .

0

We solved CA1404 as follows. The fact is that "! = 0" is an immediate call after LogonUser () or DuplicateToken ().

private static void Impersonate(string userName, string domain, string password, LogOnType logonType, LogOnProvider logonProvider, ImpersonationLevel impersonationLevel)
{
    var token = IntPtr.Zero;
    var tokenDuplicate = IntPtr.Zero;
    if (NativeMethods.RevertToSelf())
    {
        var logonUserSuccessful = NativeMethods.LogonUser(userName, domain, password, (int) logonType, (int) logonProvider, ref token);
        var e = Marshal.GetLastWin32Error();  // call before comparison against 0 to avoid CA1404
        if (logonUserSuccessful != 0)
        {
            var duplicateTokenSuccessful = NativeMethods.DuplicateToken(token, (int) impersonationLevel, ref tokenDuplicate);
            e = Marshal.GetLastWin32Error();  // call before comparison against 0 to avoid CA1404
            if (duplicateTokenSuccessful != 0)
            {
                /* CA2000 */
                using (var tempWindowsIdentity = new WindowsIdentity(tokenDuplicate))
                {
                    _impersonationContext = tempWindowsIdentity.Impersonate();
                    return;
                }
            }
        }
    }
    throw new Win32Exception(e);
}
-1
source

All Articles