Reputation: 2371
There is object of type SECURITY_IDENTIFIER structure in the file. I need to get owner SID from this structure. In order to do this I call GetSecurityDescriptorOwner
WinAPI function and create System.Security.Principal.SecurityIdentifier
(it has overload taking IntPtr as an argument)
The problem is this structure in file is broken sometimes, so the pointer I get from GetSecurityDescriptorOwner is invalid. It's not IntPtr.Zero, it's invalid, so when I create object of type SecurityIdentifier
I get AccessViolationException
, which is not possible to catch with .NET 4 with a simple try-catch.
I am aware of attribute which allows to catch such exceptions, so I used it for the time being, but I don't like this solution. It's not recommended to catch Corrupted State Exceptions (CSE), but I don't see any other solutions. This WinAPI function returns me invalid pointer and I see no way to check it for validness. Any ideas?
update
WinAPI
BOOL WINAPI GetSecurityDescriptorOwner(
_In_ PSECURITY_DESCRIPTOR pSecurityDescriptor,
_Out_ PSID *pOwner,
_Out_ LPBOOL lpbOwnerDefaulted
);
Extern definition
[DllImport("Advapi32.dll")]
static extern bool GetSecurityDescriptorOwner(
IntPtr pSecurityDescriptor,
out IntPtr owner,
out bool defaulted);
update
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;
}
This code throws sometimes throws Corrupted State Exceptions from SecurityIdentifier constructor. Any solutions?
Upvotes: 4
Views: 479
Reputation: 2626
Updated:
Try this instead:
[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();
}
Upvotes: 0
Reputation: 124726
Have you tried calling IsValidSecurityDescriptor
?
[DllImport("Advapi32.dll")]
static extern bool IsValidSecurityDescriptor(IntPtr pSecurityDescriptor);
if (IsValidSecurityDescriptor(descriptorPtr) &&
GetSecurityDescriptorOwner(descriptorPtr, out ownerSid, out defaulted))
{
return new SecurityIdentifier(ownerSid);
}
Upvotes: 1