[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);
Declare Function QueryServiceObjectSecurity Lib "advapi32.dll" (TODO) As TODO
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.
None.
Please add some!
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());
}