internal static int GetSecurityInfo(
ResourceType resourceType,
string name,
SafeHandle handle,
AccessControlSections accessControlSections,
out RawSecurityDescriptor resultSd
)
{
resultSd = null;
int errorCode;
IntPtr SidOwner, SidGroup, Dacl, Sacl, ByteArray;
SecurityInfos SecurityInfos = 0;
Privilege privilege = null;
if ((accessControlSections & AccessControlSections.Owner) != 0)
{
SecurityInfos |= SecurityInfos.Owner;
}
if ((accessControlSections & AccessControlSections.Group) != 0)
{
SecurityInfos |= SecurityInfos.Group;
}
if ((accessControlSections & AccessControlSections.Access) != 0)
{
SecurityInfos |= SecurityInfos.DiscretionaryAcl;
}
if ((accessControlSections & AccessControlSections.Audit) != 0)
{
SecurityInfos |= SecurityInfos.SystemAcl;
privilege = new Privilege(Privilege.Security);
}
try
{
if (privilege != null)
{
try
{
privilege.Enable();
}
catch (PrivilegeNotHeldException)
{
// we will ignore this exception and press on just in case this is a remote resource
}
}
if (name != null)
{
errorCode = (int)Interop.Advapi32.GetSecurityInfoByName(name, (uint)resourceType, (uint)SecurityInfos, out SidOwner, out SidGroup, out Dacl, out Sacl, out ByteArray);
}
else if (handle != null)
{
if (handle.IsInvalid)
{
throw new ArgumentException(
SR.Argument_InvalidSafeHandle,
nameof(handle));
}
else
{
errorCode = (int)Interop.Advapi32.GetSecurityInfoByHandle(handle, (uint)resourceType, (uint)SecurityInfos, out SidOwner, out SidGroup, out Dacl, out Sacl, out ByteArray);
}
}
else
{
// both are null, shouldn't happen
// Changing from SystemException to ArgumentException as this code path is indicative of a null name argument
// as well as an accessControlSections argument with an audit flag
throw new ArgumentException();
}
if (errorCode == Interop.Errors.ERROR_SUCCESS && IntPtr.Zero.Equals(ByteArray))
{
//
// This means that the object doesn't have a security descriptor. And thus we throw
// a specific exception for the caller to catch and handle properly.
//
throw new InvalidOperationException(SR.InvalidOperation_NoSecurityDescriptor);
}
else if (errorCode == Interop.Errors.ERROR_NOT_ALL_ASSIGNED ||
errorCode == Interop.Errors.ERROR_PRIVILEGE_NOT_HELD)
{
throw new PrivilegeNotHeldException(Privilege.Security);
}
else if (errorCode == Interop.Errors.ERROR_ACCESS_DENIED ||
errorCode == Interop.Errors.ERROR_CANT_OPEN_ANONYMOUS)
{
throw new UnauthorizedAccessException();
}
if (errorCode != Interop.Errors.ERROR_SUCCESS)
{
goto Error;
}
}
catch
{
// protection against exception filter-based luring attacks
if (privilege != null)
{
privilege.Revert();
}
throw;
}
finally
{
if (privilege != null)
{
privilege.Revert();
}
}
//
// Extract data from the returned pointer
//
uint Length = Interop.Advapi32.GetSecurityDescriptorLength(ByteArray);
byte[] BinaryForm = new byte[Length];
Marshal.Copy(ByteArray, BinaryForm, 0, (int)Length);
Interop.Kernel32.LocalFree(ByteArray);
resultSd = new RawSecurityDescriptor(BinaryForm, 0);
return Interop.Errors.ERROR_SUCCESS;
Error:
if (errorCode == Interop.Errors.ERROR_NOT_ENOUGH_MEMORY)
{
throw new OutOfMemoryException();
}
return errorCode;
}