QueryServiceObjectSecurity (advapi32)
Last changed: -213.199.128.177

.
Summary
The QueryServiceObjectSecurity function retrieves a copy of the security descriptor associated with a service object. You can also use the GetNamedSecurityInfo function to retrieve a security descriptor.

C# Signature:

[DllImport("advapi32.dll", SetLastError=true)]
static extern bool QueryServiceObjectSecurity(IntPtr serviceHandle, System.Security.AccessControl.SecurityInfos secInfo, ref SECURITY_DESCRIPTOR lpSecDesrBuf, uint bufSize, out uint bufSizeNeeded);

[DllImport("advapi32.dll", SetLastError=true)]
static extern bool QueryServiceObjectSecurity(SafeHandle serviceHandle, System.Security.AccessControl.SecurityInfos secInfo, byte[] lpSecDesrBuf, uint bufSize, out uint bufSizeNeeded);

VB Signature:

Declare Function QueryServiceObjectSecurity Lib "advapi32.dll" (TODO) As TODO

User-Defined Types:

SECURITY_DESCRIPTOR

Alternative Managed API:

New in .NET v2.0: Security.AccessControl namespace, including gems to manipulate DACLs in raw (binary) form. So rather than using a ref SECURITY_DESCRIPTOR I'd advocate using a byte[] and RawSecurityDescriptor(byte[], 0). See sample code below.

Notes:

None.

Tips & Tricks:

Please add some!

Sample Code:

ServiceController sc = new ServiceController("MyServiceName");
byte [] psd = new byte[0];
uint bufSizeNeeded;
bool ok = QueryServiceObjectSecurity(sc.ServiceHandle, SecurityInfos.DiscretionaryAcl, psd, 0, out bufSizeNeeded);
if (!ok)
{
    int err = Marshal.GetLastWin32Error();
    if (err == 122) // ERROR_INSUFFICIENT_BUFFER
    {
    // expected; now we know bufsize
    psd = new byte[bufSizeNeeded];
    ok = QueryServiceObjectSecurity(sc.ServiceHandle, SecurityInfos.DiscretionaryAcl, psd, bufSizeNeeded, out bufSizeNeeded);
    }
    else
    {
    throw new ApplicationException("error calling QueryServiceObjectSecurity() to get DACL for SeaweedService: error code=" + err);
    }
}
if (!ok)
    throw new ApplicationException("error calling QueryServiceObjectSecurity(2) to get DACL for SeaweedService: error code=" + Marshal.GetLastWin32Error());

// get security descriptor via raw into DACL form so ACE
// ordering checks are done for us.
RawSecurityDescriptor rsd = new RawSecurityDescriptor(psd, 0);
RawAcl racl = rsd.DiscretionaryAcl;
DiscretionaryAcl dacl = new DiscretionaryAcl(false, false, racl);

// TODO: fiddle with the dacl to SetAccess() etc

// convert discretionary ACL back to raw form; looks like via byte[] is only way
byte[] rawdacl = new byte[dacl.BinaryLength];
dacl.GetBinaryForm(rawdacl, 0);
rsd.DiscretionaryAcl = new RawAcl(rawdacl, 0);

// set raw security descriptor on service again
byte[] rawsd = new byte[rsd.BinaryLength];
rsd.GetBinaryForm(rawsd, 0);
ok = SetServiceObjectSecurity(sc.ServiceHandle, SecurityInfos.DiscretionaryAcl, rawsd);
if (!ok)
{
     throw new ApplicationException("error calling SetServiceObjectSecurity(); error code=" + Marshal.GetLastWin32Error());
}

Documentation