在.NET中捕获AccessViolation 4.好还是坏?

时间:2012-09-06 19:11:35

标签: c# .net exception error-handling corrupted-state-exception

文件中有类型SECURITY_IDENTIFIER结构的对象。我需要从这个结构获得所有者SID。为了做到这一点,我调用GetSecurityDescriptorOwner WinAPI函数并创建System.Security.Principal.SecurityIdentifier(它有重载以IntPtr作为参数)

问题是文件中的结构有时会被破坏,因此我从GetSecurityDescriptorOwner获取的指针无效。它不是IntPtr.Zero,它是无效的,所以当我创建SecurityIdentifier类型的对象时,我得到AccessViolationException,这是不可能用简单的try-catch来捕获.NET 4。

我知道允许捕获此类异常的属性,所以我暂时使用它,但我不喜欢这个解决方案。不建议捕获Corrupted State Exceptions(CSE),但我没有看到任何其他解决方案。这个WinAPI函数返回无效指针,我看不到检查它的有效性。有什么想法吗?

更新

WinAPI的

BOOL WINAPI GetSecurityDescriptorOwner(
  _In_   PSECURITY_DESCRIPTOR pSecurityDescriptor,
  _Out_  PSID *pOwner,
  _Out_  LPBOOL lpbOwnerDefaulted
);

外部定义

[DllImport("Advapi32.dll")]
static extern bool GetSecurityDescriptorOwner(
   IntPtr pSecurityDescriptor,
   out IntPtr owner,
   out bool defaulted);

更新

private static SecurityIdentifier GetSecurityIdentifier()
{
    // Allocate managed buffer for invalid security descriptor structure (20 bytes)
    int[] b = new int[5] {1, 1, 1, 1, 1};

    // Allocate unmanaged memory for security descriptor 
    IntPtr descriptorPtr = Marshal.AllocHGlobal(b.Length);

    // Copy invalid security descriptor structure to the unmanaged buffer
    Marshal.Copy(b, 0, descriptorPtr, b.Length);

    IntPtr ownerSid;
    bool defaulted;

    if (GetSecurityDescriptorGroup(descriptorPtr, out ownerSid, out defaulted))
    {
        // GetSecurityDescriptorGroup returns true, but `ownerSid` is `1`
        // Marshal.GetLastWin32Error returns 0 here
        return new SecurityIdentifier(ownerSid);
    }

    return null;
}

此代码抛出有时会从SecurityIdentifier构造函数中抛出损坏的状态异常。任何解决方案?

2 个答案:

答案 0 :(得分:1)

您是否尝试过调用IsValidSecurityDescriptor

[DllImport("Advapi32.dll")]
static extern bool IsValidSecurityDescriptor(IntPtr pSecurityDescriptor);


if (IsValidSecurityDescriptor(descriptorPtr) && 
    GetSecurityDescriptorOwner(descriptorPtr, out ownerSid, out defaulted))
{
     return new SecurityIdentifier(ownerSid);
}

答案 1 :(得分:0)

<强>更新

请改为尝试:

    [DllImport("Advapi32.dll")]
    static extern bool GetSecurityDescriptorOwner(
       [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U4)]
       Int32[] securityDescriptor,
       [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1)] 
       out Byte[] owner,
       out Boolean defaulted);


    [DllImport("Advapi32.dll")]
    static extern bool IsValidSecurityDescriptor(
        [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U4)] 
        Int32[] securityDescriptor);

    private static SecurityIdentifier GetSecurityIdentifier()
    {
        // Allocate managed buffer for invalid security descriptor structure (20 bytes)
        Int32[] b = new[] { 1, 1, 1, 1, 1 };

        Byte[] ownerSid;
        bool defaulted;

        if (IsValidSecurityDescriptor(b) &&
            GetSecurityDescriptorOwner(b, out ownerSid, out defaulted))
        {
            return new SecurityIdentifier(ownerSid, 0);
        }

        return null;
    }

    static void Main()
    {
        for (Int32 index = 0; index < 1000; index++)
        {
            SecurityIdentifier identifier = GetSecurityIdentifier();
            String text = identifier == null ? "(none)" : identifier.Value;
            Console.WriteLine(text);
        }

        Console.ReadKey();
    }