Win32API.cs
// Copyright (C) 2016 Moriyoshi Koizumi <mozo@mozo.jp>
// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. using System; using System.Security; using System.Runtime.InteropServices; using System.Collections; using System.Collections.Generic; namespace Win32API { public sealed class Win32APIException: Exception { int code; string message; string[] arguments; public int Code { get { return code; } set { code = value; } } public override string Message { get { if (message == null) { IntPtr messageText = IntPtr.Zero; IntPtr[] _arguments = null; if (arguments != null) { _arguments = new IntPtr[arguments.Length]; for (var i = 0; i < arguments.Length; i++) { _arguments[i] = Marshal.StringToHGlobalUni(arguments[i]); } } try { uint messageTextLen = Kernel32.FormatMessage( Kernel32.FormatMessageFlags.ALLOCATE_BUFFER | Kernel32.FormatMessageFlags.FROM_SYSTEM | Kernel32.FormatMessageFlags.ARGUMENT_ARRAY, IntPtr.Zero, (uint)Code, 0, ref messageText, 0, _arguments ); if (messageTextLen != 0) { message = Marshal.PtrToStringUni(messageText, (int)messageTextLen).Trim(); } } finally { if (messageText != IntPtr.Zero) { Marshal.FreeHGlobal(messageText); } if (_arguments != null) { foreach (IntPtr a in _arguments) { Marshal.FreeHGlobal(a); } } } } return message; } } public Win32APIException(int code, params string[] arguments) { this.code = code; this.arguments = arguments; } } public sealed class UserEnv { [DllImport("userenv.dll", EntryPoint="CreateEnvironmentBlock", SetLastError=true)] public static extern bool _CreateEnvironmentBlock(out IntPtr lpEnvironment, IntPtr hToken, bool bInherit); public static IntPtr CreateEnvironmentBlock(IntPtr hToken, bool bInherit) { IntPtr retval; if (!_CreateEnvironmentBlock(out retval, hToken, bInherit)) { throw new Win32APIException(Marshal.GetLastWin32Error()); } return retval; } [DllImport("userenv.dll", EntryPoint="DestroyEnvironmentBlock", SetLastError=true)] public static extern bool _DestroyEnvironmentBlock(IntPtr lpEnvironment); public static void DestroyEnvironmentBlock(IntPtr lpEnvironment) { if (!_DestroyEnvironmentBlock(lpEnvironment)) { throw new Win32APIException(Marshal.GetLastWin32Error()); } } [StructLayout(LayoutKind.Sequential)] public struct PROFILEINFO { public int dwSize; public int dwFlags; public string lpUserName; public string lpProfilePath; public string lpDefaultPath; public string lpServerName; public string lpPolicyPath; public IntPtr hProfile; } [DllImport("userenv.dll", EntryPoint="LoadUserProfile", SetLastError=true, CharSet=CharSet.Unicode)] public static extern bool _LoadUserProfile(IntPtr hToken, ref PROFILEINFO lpProfileInfo); public static PROFILEINFO LoadUserProfile(IntPtr hToken, string userName) { PROFILEINFO retval = new PROFILEINFO(); retval.dwSize = Marshal.SizeOf(typeof(PROFILEINFO)); retval.lpUserName = userName; if (!_LoadUserProfile(hToken, ref retval)) { throw new Win32APIException(Marshal.GetLastWin32Error()); } return retval; } [DllImport("userenv.dll", EntryPoint="UnloadUserProfile", SetLastError=true, CharSet=CharSet.Unicode)] public static extern bool _UnloadUserProfile(IntPtr hToken, IntPtr hProfile); public static void UnloadUserProfile(IntPtr hToken, ref PROFILEINFO lpProfileInfo) { if (!_UnloadUserProfile(hToken, lpProfileInfo.hProfile)) { throw new Win32APIException(Marshal.GetLastWin32Error()); } } } public sealed class Kernel32 { [Flags] public enum FormatMessageFlags: uint { ALLOCATE_BUFFER = 0x00000100, IGNORE_INSERTS = 0x00000200, FROM_SYSTEM = 0x00001000, ARGUMENT_ARRAY = 0x00002000, FROM_HMODULE = 0x00000800, FROM_STRING = 0x00000400 } [DllImport("Kernel32.dll", EntryPoint="FormatMessageW", SetLastError=true)] public static extern uint FormatMessage( FormatMessageFlags dwFlags, IntPtr lpSource, uint dwMessageId, uint dwLanguageId, ref IntPtr lpBuffer, uint nSize, IntPtr[] Arguments ); [Flags] public enum CreateProcessFlags: uint { CREATE_BREAKAWAY_FROM_JOB = 0x01000000, CREATE_DEFAULT_ERROR_MODE = 0x04000000, CREATE_NEW_CONSOLE = 0x00000010, CREATE_NEW_PROCESS_GROUP = 0x00000200, CREATE_NO_WINDOW = 0x08000000, CREATE_PROTECTED_PROCESS = 0x00040000, CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000, CREATE_SEPARATE_WOW_VDM = 0x00000800, CREATE_SHARED_WOW_VDM = 0x00001000, CREATE_SUSPENDED = 0x00000004, CREATE_UNICODE_ENVIRONMENT = 0x00000400, DEBUG_ONLY_THIS_PROCESS = 0x00000002, DEBUG_PROCESS = 0x00000001, DETACHED_PROCESS = 0x00000008, EXTENDED_STARTUPINFO_PRESENT = 0x00080000, INHERIT_PARENT_AFFINITY = 0x00010000 } [Flags] public enum StartUpInfoFlags: uint { STARTF_USESHOWWINDOW = 0x00000001, STARTF_USESIZE = 0x00000002, STARTF_USEPOSITION = 0x00000004, STARTF_USECOUNTCHARS = 0x00000008, STARTF_USEFILLATTRIBUTE = 0x00000010, STARTF_RUNFULLSCREEN = 0x00000020, // ignored for non-x86 platforms STARTF_FORCEONFEEDBACK = 0x00000040, STARTF_FORCEOFFFEEDBACK = 0x00000080, STARTF_USESTDHANDLES = 0x00000100, } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct STARTUPINFO { public int cb; public IntPtr lpReserved; public string lpDesktop; public string lpTitle; public int dwX; public int dwY; public int dwXSize; public int dwYSize; public int dwXCountChars; public int dwYCountChars; public int dwFillAttribute; public StartUpInfoFlags dwFlags; public short wShowWindow; public short cbReserved2; public IntPtr lpReserved2; public IntPtr hStdInput; public IntPtr hStdOutput; public IntPtr hStdError; public STARTUPINFO( StartUpInfoFlags dwFlags = 0, string lpDesktop = null, string lpTitle = null, int dwX = CW_USEDEFAULT, int dwY = CW_USEDEFAULT, int dwXSize = CW_USEDEFAULT, int dwYSize = CW_USEDEFAULT, int dwXCountChars = 0, int dwYCountChars = 0, int dwFillAttribute = 0, short wShowWindow = 0, IntPtr hStdInput = default(IntPtr), IntPtr hStdOutput = default(IntPtr), IntPtr hStdError = default(IntPtr) ) { this.lpReserved = IntPtr.Zero; this.lpDesktop = lpDesktop; this.lpTitle = lpTitle; this.dwX = dwX; this.dwY = dwY; this.dwXSize = dwXSize; this.dwYSize = dwYSize; this.dwXCountChars = dwXCountChars; this.dwYCountChars = dwYCountChars; this.dwFillAttribute = dwFillAttribute; this.dwFlags = dwFlags; this.wShowWindow = wShowWindow; this.cbReserved2 = 0; this.lpReserved2 = IntPtr.Zero; this.hStdInput = hStdInput; this.hStdOutput = hStdOutput; this.hStdError = hStdError; this.cb = Marshal.SizeOf(typeof(STARTUPINFO)); } } [StructLayout(LayoutKind.Sequential)] public struct PROCESS_INFORMATION { public IntPtr hProcess; public IntPtr hThread; public int dwProcessId; public int dwThreadId; } public const int CW_USEDEFAULT = -1; [DllImport("kernel32.dll", EntryPoint="CreateProcessW", SetLastError=true, CharSet=CharSet.Unicode)] public static extern bool _CreateProcess( string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, CreateProcessFlags dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation ); public static PROCESS_INFORMATION CreateProcess( string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, CreateProcessFlags dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref STARTUPINFO lpStartupInfo ) { PROCESS_INFORMATION retval; if (!_CreateProcess( lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, ref lpStartupInfo, out retval )) { throw new Win32APIException(Marshal.GetLastWin32Error(), lpApplicationName); } return retval; } [DllImport("kernel32.dll", EntryPoint="CloseHandle", SetLastError=true)] public static extern bool _CloseHandle(IntPtr hObject); public static void CloseHandle(IntPtr hObject) { if (!_CloseHandle(hObject)) { throw new Win32APIException(Marshal.GetLastWin32Error()); } } [DllImport("Kernel32.dll", EntryPoint="RtlMoveMemory", SetLastError=false)] public static extern void MoveMemory(IntPtr dest, IntPtr src, uint size); public enum WaitCode: uint { OBJECT_0 = 0x00000000, ABANDONED = 0x00000080, TIMEOUT = 0x00000102, FAILED = 0xFFFFFFFF } [DllImport("kernel32.dll", EntryPoint="WaitForSingleObject", SetLastError=true)] public static extern WaitCode _WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds); public static WaitCode WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds) { WaitCode retval = _WaitForSingleObject(hHandle, dwMilliseconds); if (retval == WaitCode.FAILED) { throw new Win32APIException(Marshal.GetLastWin32Error()); } return retval; } [DllImport("kernel32.dll", EntryPoint="WaitForInputIdle", SetLastError=true)] public static extern WaitCode _WaitForInputIdle(IntPtr hHandle, uint dwMilliseconds); public static WaitCode WaitForInputIdle(IntPtr hHandle, uint dwMilliseconds) { WaitCode retval = _WaitForInputIdle(hHandle, dwMilliseconds); if (retval == WaitCode.FAILED) { throw new Win32APIException(Marshal.GetLastWin32Error()); } return retval; } [DllImport("kernel32.dll", EntryPoint="GetExitCodeProcess", SetLastError=true)] public static extern bool _GetExitCodeProcess(IntPtr hProcess, out uint lpExitCode); public static uint GetExitCodeProcess(IntPtr hProcess) { uint retval; if (!_GetExitCodeProcess(hProcess, out retval)) { throw new Win32APIException(Marshal.GetLastWin32Error()); } return retval; } [DllImport("kernel32.dll", EntryPoint="GetCurrentProcess", SetLastError=false)] public static extern IntPtr GetCurrentProcess(); [DllImport("kernel32.dll", EntryPoint="GetProcessId", SetLastError=false)] public static extern uint GetProcessId(IntPtr hProcess); } public sealed class User32 { public enum ShowWindowCommand { SW_HIDE = 0, SW_SHOWNORMAL = 1, SW_NORMAL = 1, SW_SHOWMINIMIZED = 2, SW_SHOWMAXIMIZED = 3, SW_MAXIMIZE = 3, SW_SHOWNOACTIVATE = 4, SW_SHOW = 5, SW_MINIMIZE = 6, SW_SHOWMINNOACTIVE = 7, SW_SHOWNA = 8, SW_RESTORE = 9, SW_SHOWDEFAULT = 10, SW_MAX = 10 } [DllImport("user32.dll", EntryPoint="GetProcessWindowStation", SetLastError=true)] public static extern IntPtr GetProcessWindowStation(); public enum UserObjectInformationIndex: int { UOI_FLAGS = 1, UOI_NAME, UOI_TYPE, UOI_USER_SID, UOI_HEAPSIZE, UOI_IO } public struct USEROBJECTFLAGS { public bool fInherit; public bool fReserved; public uint dwFlags; }; [DllImport("user32.dll", EntryPoint="GetUserObjectInformation", SetLastError=true)] public static extern bool _GetUserObjectInformation( IntPtr hObj, UserObjectInformationIndex nIndex, IntPtr pvInfo, uint nLength, out uint lpnLengthNeeded ); public static object GetUserObjectInformation(IntPtr hObj, UserObjectInformationIndex nIndex) { uint len; _GetUserObjectInformation(hObj, nIndex, IntPtr.Zero, (uint)0, out len); IntPtr buf = Marshal.AllocHGlobal((int)len); try { if (!_GetUserObjectInformation(hObj, nIndex, buf, len, out len)) { throw new Win32APIException(Marshal.GetLastWin32Error()); } if (nIndex == UserObjectInformationIndex.UOI_FLAGS) { return Marshal.PtrToStructure<USEROBJECTFLAGS>(buf); } else { byte[] retval = new byte[len]; Marshal.Copy(buf, retval, 0, (int)len); return retval; } } finally { Marshal.FreeHGlobal(buf); } } public delegate bool EnumDesktopProc( [MarshalAs(UnmanagedType.LPWStr)] string lpszDesktop, uint lParam ); [DllImport("user32.dll", EntryPoint="EnumDesktopsW", SetLastError=true, CharSet=CharSet.Unicode)] public static extern bool _EnumDesktops( IntPtr hwinsta, [MarshalAs(UnmanagedType.FunctionPtr)] EnumDesktopProc lpEnumFunc, uint lParam ); public static IList<string> EnumDesktops(IntPtr hwinsta) { List<string> retval = new List<string>(); if (!_EnumDesktops( hwinsta, delegate (string lpszDesktop, uint lParam) { retval.Add(lpszDesktop); return true; }, 0)) { throw new Win32APIException(Marshal.GetLastWin32Error()); } return retval; } [DllImport("user32.dll", EntryPoint="OpenDesktopW", SetLastError=true, CharSet=CharSet.Unicode)] public static extern IntPtr _OpenDesktop( string lpszDesktop, uint dwFlags, bool fInherit, AdvApi32.ACCESS_MASK dwDesiredAccess ); public static IntPtr OpenDesktop(string lpszDesktop, uint dwFlags, bool fInherit, AdvApi32.ACCESS_MASK dwDesiredAccess) { IntPtr retval = _OpenDesktop(lpszDesktop, dwFlags, fInherit, dwDesiredAccess); if (retval == IntPtr.Zero) { throw new Win32APIException(Marshal.GetLastWin32Error()); } return retval; } [DllImport("user32.dll", EntryPoint="CloseDesktop", SetLastError=true)] public static extern bool _CloseDesktop(IntPtr hDesktop); public static void CloseDesktop(IntPtr hDesktop) { if (!_CloseDesktop(hDesktop)) { throw new Win32APIException(Marshal.GetLastWin32Error()); } } [Flags] public enum DESKTOP_ACCESS_MASK: uint { DESKTOP_READOBJECTS = 0x0001, DESKTOP_CREATEWINDOW = 0x0002, DESKTOP_CREATEMENU = 0x0004, DESKTOP_HOOKCONTROL = 0x0008, DESKTOP_JOURNALRECORD = 0x0010, DESKTOP_JOURNALPLAYBACK = 0x0020, DESKTOP_ENUMERATE = 0x0040, DESKTOP_WRITEOBJECTS = 0x0080, DESKTOP_SWITCHDESKTOP = 0x0100 } } public sealed class AdvApi32 { [StructLayout(LayoutKind.Sequential)] public struct SECURITY_ATTRIBUTES { public int nLength; public IntPtr lpSecurityDescriptor; public int bInheritHandle; } public enum LogonType: int { INTERACTIVE = 2, NETWORK, BATCH, SERVICE, UNLOCK = 7, NETWORK_CLEARTEXT, NEW_CREDENTIALS } public enum LogonProvider: int { DEFAULT = 0, WINNT35 = 1, WINNT40 = 2, WINNT50 = 3 } [DllImport("advapi32.dll", EntryPoint="LogonUserW", SetLastError=true, CharSet=CharSet.Unicode)] public static extern bool _LogonUser( string pszUserName, string pszDomain, string pszPassword, LogonType dwLogonType, LogonProvider dwLogonProvider, out IntPtr phToken ); [DllImport("advapi32.dll", EntryPoint="LogonUserW", SetLastError=true, CharSet=CharSet.Unicode)] public static extern bool _LogonUser( string pszUserName, string pszDomain, IntPtr pszPassword, LogonType dwLogonType, LogonProvider dwLogonProvider, out IntPtr phToken ); public static bool _LogonUser( string pszUserName, string pszDomain, SecureString pszPassword, LogonType dwLogonType, LogonProvider dwLogonProvider, out IntPtr phToken ) { IntPtr password = Marshal.SecureStringToCoTaskMemUnicode(pszPassword); try { return _LogonUser( pszUserName, pszDomain, password, dwLogonType, dwLogonProvider, out phToken ); } finally { Marshal.ZeroFreeCoTaskMemUnicode(password); } } public static IntPtr LogonUser( string pszUserName, string pszDomain, string pszPassword, LogonType dwLogonType, LogonProvider dwLogonProvider ) { IntPtr token = IntPtr.Zero; if (!_LogonUser(pszUserName, pszDomain, pszPassword, dwLogonType, dwLogonProvider, out token)) { throw new Win32APIException(Marshal.GetLastWin32Error()); } return token; } public static IntPtr LogonUser( string pszUserName, string pszDomain, SecureString pszPassword, LogonType dwLogonType, LogonProvider dwLogonProvider ) { IntPtr token = IntPtr.Zero; if (!_LogonUser(pszUserName, pszDomain, pszPassword, dwLogonType, dwLogonProvider, out token)) { throw new Win32APIException(Marshal.GetLastWin32Error()); } return token; } [DllImport("advapi32.dll", EntryPoint="CreateProcessAsUserW", SetLastError=true, CharSet=CharSet.Unicode)] public static extern bool _CreateProcessAsUser( IntPtr hToken, string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, Kernel32.CreateProcessFlags dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref Kernel32.STARTUPINFO lpStartupInfo, out Kernel32.PROCESS_INFORMATION lpProcessInformation ); public static Kernel32.PROCESS_INFORMATION CreateProcessAsUser( IntPtr hToken, string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, Kernel32.CreateProcessFlags dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref Kernel32.STARTUPINFO lpStartupInfo ) { Kernel32.PROCESS_INFORMATION retval; if (!_CreateProcessAsUser( hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, ref lpStartupInfo, out retval )) { throw new Win32APIException(Marshal.GetLastWin32Error(), lpApplicationName); } return retval; } [DllImport("advapi32.dll", EntryPoint="ImpersonateLoggedOnUser", SetLastError=true)] public static extern bool _ImpersonateLoggedOnUser(IntPtr hToken); public static void ImpersonateLoggedOnUser(IntPtr hToken) { if (!_ImpersonateLoggedOnUser(hToken)) { throw new Win32APIException(Marshal.GetLastWin32Error()); } } [DllImport("advapi32.dll", EntryPoint="ConvertSidToStringSidW", SetLastError=true)] public static extern bool _ConvertSidToStringSid(IntPtr sid, out IntPtr stringSid); public static string ConvertSidToStringSid(IntPtr sid) { IntPtr str; if (!_ConvertSidToStringSid(sid, out str)) { throw new Win32APIException(Marshal.GetLastWin32Error()); } try { return Marshal.PtrToStringUni(str); } finally { Marshal.FreeHGlobal(str); } } [Flags] public enum SECURITY_INFORMATION: uint { OWNER = 0x00000001, GROUP = 0x00000002, DACL = 0x00000004, SACL = 0x00000008, UNPROTECTED_SACL = 0x10000000, UNPROTECTED_DACL = 0x20000000, PROTECTED_SACL = 0x40000000, PROTECTED_DACL = 0x80000000 } public enum SE_OBJECT_TYPE { UNKNOWN_OBJECT_TYPE = 0, FILE_OBJECT, SERVICE, PRINTER, REGISTRY_KEY, LMSHARE, KERNEL_OBJECT, WINDOW_OBJECT, DS_OBJECT, DS_OBJECT_ALL, PROVIDER_DEFINED_OBJECT, WMIGUID_OBJECT, REGISTRY_WOW64_32KEY } [DllImport("advapi32.dll", EntryPoint="FreeSid", SetLastError=true)] public static extern IntPtr FreeSid(IntPtr sid); [DllImport("advapi32.dll", EntryPoint="GetLengthSid", SetLastError=true)] public static extern uint GetLengthSid(IntPtr sid); [DllImport("advapi32.dll", EntryPoint="ConvertStringSidToSidW", SetLastError=true, CharSet=CharSet.Unicode)] public static extern bool _ConvertStringSidToSid(string stringSid, out IntPtr sid); public static IntPtr ConvertStringSidToSid(string stringSid) { IntPtr retval; if (!_ConvertStringSidToSid(stringSid, out retval)) { throw new Win32APIException(Marshal.GetLastWin32Error()); } return retval; } public static int ConvertStringSidToSid(string stringSid, IntPtr buf) { string[] components = stringSid.Split('-'); if (components.Length < 3 || components.Length > 10 || components[0] != "S") { throw new ArgumentException(string.Format("Specified string ({}) is not a valid string SID", stringSid)); } int nSubauthorities = components.Length - 3; int size = 8 + nSubauthorities * 4; if (buf != IntPtr.Zero) { int revision = int.Parse(components[1]); long identifierAuthority = long.Parse(components[2]); Marshal.WriteByte(buf + 0, (byte)revision); Marshal.WriteByte(buf + 1, (byte)nSubauthorities); Marshal.WriteByte(buf + 2, (byte)((identifierAuthority >> 40) & 255)); Marshal.WriteByte(buf + 3, (byte)((identifierAuthority >> 32) & 255)); Marshal.WriteByte(buf + 4, (byte)((identifierAuthority >> 24) & 255)); Marshal.WriteByte(buf + 5, (byte)((identifierAuthority >> 16) & 255)); Marshal.WriteByte(buf + 6, (byte)((identifierAuthority >> 8) & 255)); Marshal.WriteByte(buf + 7, (byte)((identifierAuthority >> 0) & 255)); for (int i = 0; i < nSubauthorities; i++) { Marshal.WriteInt32(buf + 8 + i * 4, (int)uint.Parse(components[i + 3])); } } return size; } [StructLayout(LayoutKind.Sequential)] public struct _ACL { byte AclRevision; byte Sbz1; ushort AclSize; ushort AceCount; ushort Sbz2; } public enum AceType: byte { ACCESS_ALLOWED_ACE_TYPE = 0x0, ACCESS_MIN_MS_ACE_TYPE = 0x0, ACCESS_DENIED_ACE_TYPE = 0x1, SYSTEM_AUDIT_ACE_TYPE = 0x2, SYSTEM_ALARM_ACE_TYPE = 0x3, ACCESS_MAX_MS_V2_ACE_TYPE = 0x3, ACCESS_ALLOWED_COMPOUND_ACE_TYPE = 0x4, ACCESS_MAX_MS_V3_ACE_TYPE = 0x4, ACCESS_ALLOWED_OBJECT_ACE_TYPE = 0x5, ACCESS_MIN_MS_OBJECT_ACE_TYPE = 0x5, ACCESS_DENIED_OBJECT_ACE_TYPE = 0x6, SYSTEM_AUDIT_OBJECT_ACE_TYPE = 0x7, SYSTEM_ALARM_OBJECT_ACE_TYPE = 0x8, ACCESS_MAX_MS_OBJECT_ACE_TYPE = 0x8, ACCESS_MAX_MS_V4_ACE_TYPE = 0x8, ACCESS_MAX_MS_ACE_TYPE = 0x8, ACCESS_ALLOWED_CALLBACK_ACE_TYPE = 0x9, ACCESS_DENIED_CALLBACK_ACE_TYPE = 0xA, ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE = 0xB, ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE = 0xC, SYSTEM_AUDIT_CALLBACK_ACE_TYPE = 0xD, SYSTEM_ALARM_CALLBACK_ACE_TYPE = 0xE, SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE = 0xF, SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE = 0x10, SYSTEM_MANDATORY_LABEL_ACE_TYPE = 0x11, SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE = 0x12, SYSTEM_SCOPED_POLICY_ID_ACE_TYPE = 0x13, ACCESS_MAX_MS_V5_ACE_TYPE = 0x13 } [Flags] public enum AceFlags: byte { OBJECT_INHERIT_ACE = 0x1, CONTAINER_INHERIT_ACE = 0x2, NO_PROPAGATE_INHERIT_ACE = 0x4, INHERIT_ONLY_ACE = 0x8, INHERITED_ACE = 0x10, VALID_INHERIT_FLAGS = 0x1F, SUCCESSFUL_ACCESS_ACE_FLAG = 0x40, FAILED_ACCESS_ACE_FLAG = 0x80 } [Flags] public enum ACCESS_MASK: uint { DELETE = 0x00010000, READ_CONTROL = 0x00020000, WRITE_DAC = 0x00040000, WRITE_OWNER = 0x00080000, SYNCHRONIZE = 0x00100000, STANDARD_RIGHTS_REQUIRED = 0x000F0000, STANDARD_RIGHTS_READ = READ_CONTROL, STANDARD_RIGHTS_WRITE = READ_CONTROL, STANDARD_RIGHTS_EXECUTE = READ_CONTROL, STANDARD_RIGHTS_ALL = 0x001F0000, SPECIFIC_RIGHTS_ALL = 0x0000FFFF, ACCESS_SYSTEM_SECURITY = 0x01000000, MAXIMUM_ALLOWED = 0x02000000, GENERIC_READ = 0x80000000, GENERIC_WRITE = 0x40000000, GENERIC_EXECUTE = 0x20000000, GENERIC_ALL = 0x10000000 } [StructLayout(LayoutKind.Sequential)] struct _ACE_HEADER { AceType AceType; AceFlags AceFlags; ushort AceSize; } [StructLayout(LayoutKind.Sequential)] public struct _ACCESS_ALLOWED_ACE { _ACE_HEADER Header; ACCESS_MASK Mask; uint SidStart; } [StructLayout(LayoutKind.Sequential)] public struct _ACCESS_ALLOWED_CALLBACK_ACE { _ACE_HEADER Header; ACCESS_MASK Mask; uint SidStart; } public interface IACE { AceType AceType { get; } AceFlags AceFlags { get; } int Length { get; } int Render(IntPtr p); } public abstract class ACE: IACE { AceFlags aceFlags; public abstract AceType AceType { get; } public AceFlags AceFlags { get { return aceFlags; } set { aceFlags = value; } } public abstract int Length { get; } public abstract int Render(IntPtr p); protected ACE(AceFlags aceFlags) { this.aceFlags = aceFlags; } } public class OpaqueACE: IACE { IntPtr ptr; public AceType AceType { get { return (AceType)Marshal.ReadByte(ptr, 0); } } public AceFlags AceFlags { get { return (AceFlags)Marshal.ReadByte(ptr, 1); } } public int Length { get { return (int)(ushort)Marshal.ReadInt16(ptr, 2); } } public int Render(IntPtr buf) { int length = Length; Kernel32.MoveMemory(buf, ptr, (uint)length); return length; } public OpaqueACE(IntPtr ptr) { this.ptr = ptr; } } public class AccessAllowed: ACE { public override AceType AceType { get { return AceType.ACCESS_ALLOWED_ACE_TYPE; } } public ACCESS_MASK AccessMask; public string SID; public override int Length { get { return 4 + 4 + ConvertStringSidToSid(SID, IntPtr.Zero); } } public override int Render(IntPtr buf) { Marshal.WriteByte(buf + 0, (byte)AceType); Marshal.WriteByte(buf + 1, (byte)AceFlags); Marshal.WriteInt32(buf + 4, (int)AccessMask); int aceSize = 8 + ConvertStringSidToSid(SID, buf + 8); Marshal.WriteInt16(buf + 2, (short)(ushort)aceSize); return aceSize; } public AccessAllowed(AceFlags aceFlags, ACCESS_MASK accessMask, string sid): base(aceFlags) { this.AccessMask = accessMask; this.SID = sid; } } public const int MIN_ACL_REVISION = 2; public const int MAX_ACL_REVISION = 4; public interface IACL: IEnumerable<IACE> { IntPtr Render(); int Count { get; } int Length { get; } } public class ACEEnumerator: IEnumerator<IACE> { IACE current; IntPtr pAcl; IntPtr pEnd; IntPtr p; int i; int count; public IACE Current { get { return current; } } object IEnumerator.Current { get { return Current; } } public bool MoveNext() { if (i >= count || (long)p >= (long)pEnd) { return false; } AceType aceType = (AceType)Marshal.ReadByte(p, 0); AceFlags aceFlags = (AceFlags)Marshal.ReadByte(p, 1); int aceSize = (int)(ushort)Marshal.ReadInt16(p, 2); IACE ace = null; switch (aceType) { case AceType.ACCESS_ALLOWED_ACE_TYPE: ACCESS_MASK accessMask = (ACCESS_MASK)Marshal.ReadInt32(p, 4); ace = new AccessAllowed(aceFlags, accessMask, ConvertSidToStringSid(p + 8)); break; default: ace = new OpaqueACE(p); break; } current = ace; p += aceSize; i++; return true; } public void Reset() { this.p = pAcl + 8; this.i = 0; } public void Dispose() { } public ACEEnumerator(IntPtr pAcl, int count) { int aclRevision = (int)Marshal.ReadByte(pAcl, 0); if (aclRevision < MIN_ACL_REVISION || aclRevision > MAX_ACL_REVISION) { throw new ArgumentException(string.Format("Invalid ACL revision: {}", aclRevision)); } int aclSize = (int)(ushort)Marshal.ReadInt16(pAcl, 2); int aclCount = count; this.pAcl = pAcl; this.pEnd = pAcl + 8 + aclSize; this.count = aclCount; Reset(); } } public class ACLView: IACL { IntPtr pAcl; public IntPtr Ptr { get { return pAcl; } } public IEnumerator<IACE> GetEnumerator() { return new ACEEnumerator(pAcl, Count); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public int Count { get { return (int)(ushort)Marshal.ReadInt16(pAcl, 4); } } public int Length { get { return (ushort)Marshal.ReadInt16(pAcl, 2); } } public ACLView(IntPtr pAcl) { this.pAcl = pAcl; } public IntPtr Render() { uint aclSize = (uint)Length; IntPtr buf = Marshal.AllocHGlobal((int)aclSize); Kernel32.MoveMemory(buf, pAcl, aclSize); return buf; } } public class ACL: List<IACE>, IACL { public int Length { get { int aclSize = 8; foreach (IACE ace in this) { aclSize += ace.Length; } return aclSize; } } public IntPtr Render() { int aclSize = Length; IntPtr buf = Marshal.AllocHGlobal(aclSize); Marshal.WriteByte(buf, 2); Marshal.WriteInt16(buf + 2, (short)aclSize); Marshal.WriteInt16(buf + 4, (short)Count); IntPtr p = buf + 8; foreach (IACE ace in this) { p += ace.Render(p); } return buf; } public ACL(): base() {} public ACL(IEnumerable<IACE> enumerable): base(enumerable) {} } [Flags] public enum SECURITY_DESCRIPTOR_CONTROL: ushort { SE_OWNER_DEFAULTED = 0x0001, SE_GROUP_DEFAULTED = 0x0002, SE_DACL_PRESENT = 0x0004, SE_DACL_DEFAULTED = 0x0008, SE_SACL_PRESENT = 0x0010, SE_SACL_DEFAULTED = 0x0020, SE_DACL_AUTO_INHERIT_REQ = 0x0100, SE_SACL_AUTO_INHERIT_REQ = 0x0200, SE_SACL_AUTO_INHERITED = 0x0800, SE_DACL_PROTECTED = 0x1000, SE_SACL_PROTECTED = 0x2000, SE_RM_CONTROL_VALID = 0x4000, SE_SELF_RELATIVE = 0x8000 } public const int SECURITY_DESCRIPTOR_REVISION = 1; [StructLayout(LayoutKind.Sequential)] public struct _SECURITY_DESCRIPTOR { byte Revision; byte Sbz1; SECURITY_DESCRIPTOR_CONTROL Control; IntPtr Owner; IntPtr Group; IntPtr Sacl; IntPtr Dacl; }; [DllImport("advapi32.dll", EntryPoint="GetSecurityDescriptorOwner", SetLastError=true)] public static extern bool _GetSecurityDescriptorOwner( IntPtr pSecurityDescriptor, out IntPtr owner, out bool lpbOwnerDefaulted ); public static IntPtr GetSecurityDescriptorOwner(IntPtr pSecurityDescriptor, out bool defaulted) { IntPtr retval; if (!_GetSecurityDescriptorOwner(pSecurityDescriptor, out retval, out defaulted)) { throw new Win32APIException(Marshal.GetLastWin32Error()); } return retval; } public static IntPtr GetSecurityDescriptorOwner(IntPtr pSecurityDescriptor) { bool _; return GetSecurityDescriptorOwner(pSecurityDescriptor, out _); } [DllImport("advapi32.dll", EntryPoint="GetSecurityDescriptorGroup", SetLastError=true)] public static extern bool _GetSecurityDescriptorGroup( IntPtr pSecurityDescriptor, out IntPtr owner, out bool lpbGroupDefaulted ); public static IntPtr GetSecurityDescriptorGroup(IntPtr pSecurityDescriptor, out bool defaulted) { IntPtr retval; if (!_GetSecurityDescriptorGroup(pSecurityDescriptor, out retval, out defaulted)) { throw new Win32APIException(Marshal.GetLastWin32Error()); } return retval; } public static IntPtr GetSecurityDescriptorGroup(IntPtr pSecurityDescriptor) { bool _; return GetSecurityDescriptorGroup(pSecurityDescriptor, out _); } [DllImport("advapi32.dll", EntryPoint="GetSecurityDescriptorDacl", SetLastError=true)] public static extern bool _GetSecurityDescriptorDacl( IntPtr pSecurityDescriptor, out bool lpbDaclPresent, out IntPtr pDacl, out bool lpbDaclDefaulted ); public static IntPtr GetSecurityDescriptorDacl(IntPtr pSecurityDescriptor, out bool defaulted) { IntPtr retval = IntPtr.Zero; bool present; if (!_GetSecurityDescriptorDacl(pSecurityDescriptor, out present, out retval, out defaulted)) { throw new Win32APIException(Marshal.GetLastWin32Error()); } return retval; } public static IntPtr GetSecurityDescriptorDacl(IntPtr pSecurityDescriptor) { bool _; return GetSecurityDescriptorDacl(pSecurityDescriptor, out _); } [DllImport("advapi32.dll", EntryPoint="GetSecurityDescriptorSacl", SetLastError=true)] public static extern bool _GetSecurityDescriptorSacl( IntPtr pSecurityDescriptor, out bool lpbSaclPresent, out IntPtr pSacl, out bool lpbSaclDefaulted ); public static IntPtr GetSecurityDescriptorSacl(IntPtr pSecurityDescriptor, out bool defaulted) { IntPtr retval = IntPtr.Zero; bool present; if (!_GetSecurityDescriptorSacl(pSecurityDescriptor, out present, out retval, out defaulted)) { throw new Win32APIException(Marshal.GetLastWin32Error()); } return retval; } public static IntPtr GetSecurityDescriptorSacl(IntPtr pSecurityDescriptor) { bool _; return GetSecurityDescriptorSacl(pSecurityDescriptor, out _); } [DllImport("advapi32.dll", EntryPoint="InitializeSecurityDescriptor", SetLastError=true)] public static extern bool _InitializeSecurityDescriptor(IntPtr pSecurityDescriptor, uint dwRevision); public static void InitializeSecurityDescriptor(IntPtr pSecurityDescriptor, uint dwRevision) { if (!_InitializeSecurityDescriptor(pSecurityDescriptor, dwRevision)) { throw new Win32APIException(Marshal.GetLastWin32Error()); } } public class SecurityDescriptor: IDisposable { class DummyACL: IACL { public IEnumerator<IACE> GetEnumerator() { return null; } IEnumerator IEnumerable.GetEnumerator() { return null; } public int Count { get { return -1; } } public int Length { get { return 0; } } internal DummyACL() {} public IntPtr Render() { return IntPtr.Zero; } } public static readonly string DEFAULTED_SID = "DEFAULTED"; public static readonly IACL DEFAULTED_ACL = new DummyACL(); bool disposed; static readonly int descriptorSize = Marshal.SizeOf(typeof(_SECURITY_DESCRIPTOR)); IntPtr pSecurityDescriptor; bool shouldBeFreed; bool ownerDefaulted; IntPtr? pSidOwner; bool ownerSet; string owner; bool groupDefaulted; IntPtr? pSidGroup; bool groupSet; string group; bool saclDefaulted; IntPtr? pSacl; bool saclSet; IACL sacl; bool daclDefaulted; IntPtr? pDacl; bool daclSet; IACL dacl; void RenderOwner() { if (!ownerSet) { if (pSidOwner == null) { pSidOwner = GetSecurityDescriptorOwner(pSecurityDescriptor); } owner = pSidOwner != IntPtr.Zero ? ConvertSidToStringSid((IntPtr)pSidOwner): null; ownerSet = true; } } public string Owner { get { RenderOwner(); return owner; } set { if (value == DEFAULTED_SID) { OwnerDefaulted = true; return; } owner = value; pSidOwner = null; ownerSet = true; ownerDefaulted = false; ResetSecurityDescriptor(); } } public bool OwnerDefaulted { get { return ownerDefaulted; } set { if (ownerDefaulted != value) { ownerDefaulted = value; if (value) { owner = null; pSidOwner = null; ownerSet = false; ResetSecurityDescriptor(); } } } } public IntPtr? PSidOwner { get { PopulateSecurityDescriptor(); return pSidOwner; } } void RenderGroup() { if (!groupSet) { if (pSidGroup == null) { pSidGroup = GetSecurityDescriptorGroup(pSecurityDescriptor); } group = pSidGroup != IntPtr.Zero ? ConvertSidToStringSid((IntPtr)pSidGroup): null; groupSet = true; } } public string Group { get { RenderGroup(); return group; } set { if (value == DEFAULTED_SID) { GroupDefaulted = true; return; } group = value; pSidGroup = null; groupSet = true; ResetSecurityDescriptor(); } } public bool GroupDefaulted { get { return groupDefaulted; } set { if (groupDefaulted != value) { groupDefaulted = value; if (value) { group = null; pSidGroup = null; groupSet = false; ResetSecurityDescriptor(); } } } } public IntPtr? PSidGroup { get { PopulateSecurityDescriptor(); return pSidGroup; } } void RenderSacl() { if (!saclSet) { if (pSacl == null) { pSacl = GetSecurityDescriptorSacl(pSecurityDescriptor); } sacl = pSacl != IntPtr.Zero ? new ACLView((IntPtr)pSacl): null; saclSet = true; } } public IACL Sacl { get { RenderSacl(); return sacl; } set { if (value == DEFAULTED_ACL) { SaclDefaulted = true; return; } sacl = value; pSacl = null; saclSet = true; ResetSecurityDescriptor(); } } public bool SaclDefaulted { get { return saclDefaulted; } set { if (saclDefaulted != value) { saclDefaulted = value; if (value) { sacl = null; pSacl = null; saclSet = false; ResetSecurityDescriptor(); } } } } public IntPtr? PSacl { get { PopulateSecurityDescriptor(); return pSacl; } } void RenderDacl() { if (!daclSet) { if (pDacl == null) { pDacl = GetSecurityDescriptorSacl(pSecurityDescriptor); } dacl = pDacl != IntPtr.Zero ? new ACLView((IntPtr)pDacl): null; daclSet = true; } } public IACL Dacl { get { RenderDacl(); return dacl; } set { if (value == DEFAULTED_ACL) { DaclDefaulted = true; return; } dacl = value; pDacl = null; daclSet = true; ResetSecurityDescriptor(); } } public bool DaclDefaulted { get { return daclDefaulted; } set { if (daclDefaulted != value) { daclDefaulted = value; if (value) { dacl = null; pDacl = null; daclSet = false; ResetSecurityDescriptor(); } } } } public IntPtr? PDacl { get { PopulateSecurityDescriptor(); return pDacl; } } void PopulateSecurityDescriptor() { if (pSecurityDescriptor == IntPtr.Zero) { pSecurityDescriptor = Render(ref pSidOwner, ref pSidGroup, ref pSacl, ref pDacl); shouldBeFreed = true; } } public IntPtr Ptr { get { PopulateSecurityDescriptor(); return pSecurityDescriptor; } } private void FreeSecurityDescriptor() { SECURITY_DESCRIPTOR_CONTROL control = (SECURITY_DESCRIPTOR_CONTROL)(ushort)Marshal.ReadInt16(pSecurityDescriptor, 2); if ((control & SECURITY_DESCRIPTOR_CONTROL.SE_SELF_RELATIVE) == 0) { if (pSidOwner != null && pSidOwner != IntPtr.Zero) { Marshal.FreeHGlobal((IntPtr)pSidOwner); pSidOwner = null; } if (pSidGroup != null && pSidGroup != IntPtr.Zero) { Marshal.FreeHGlobal((IntPtr)pSidGroup); pSidGroup = null; } if (pSacl != null && pSacl != IntPtr.Zero) { Marshal.FreeHGlobal((IntPtr)pSacl); pSacl = null; } if (pDacl != null && pDacl != IntPtr.Zero) { Marshal.FreeHGlobal((IntPtr)pDacl); pDacl = null; } } if (shouldBeFreed && pSecurityDescriptor != IntPtr.Zero) { Marshal.FreeHGlobal(pSecurityDescriptor); pSecurityDescriptor = IntPtr.Zero; } } private void ResetSecurityDescriptor() { RenderOwner(); RenderGroup(); RenderSacl(); RenderDacl(); FreeSecurityDescriptor(); } public IntPtr Render(ref IntPtr? pSidOwner, ref IntPtr? pSidGroup, ref IntPtr? pSacl, ref IntPtr? pDacl) { IntPtr ptr = Marshal.AllocHGlobal(descriptorSize); InitializeSecurityDescriptor(ptr, SECURITY_DESCRIPTOR_REVISION); SECURITY_DESCRIPTOR_CONTROL flags = 0; try { if (Owner != null) { pSidOwner = ConvertStringSidToSid(Owner); } if (ownerDefaulted) { flags |= SECURITY_DESCRIPTOR_CONTROL.SE_OWNER_DEFAULTED; } Marshal.WriteIntPtr(ptr + 4 + IntPtr.Size * 0, pSidOwner.GetValueOrDefault(IntPtr.Zero)); if (Group != null) { pSidGroup = ConvertStringSidToSid(Group); } if (groupDefaulted) { flags |= SECURITY_DESCRIPTOR_CONTROL.SE_GROUP_DEFAULTED; } Marshal.WriteIntPtr(ptr + 4 + IntPtr.Size * 1, pSidGroup.GetValueOrDefault(IntPtr.Zero)); if (saclDefaulted) { flags |= SECURITY_DESCRIPTOR_CONTROL.SE_SACL_DEFAULTED; } if (sacl != null) { pSacl = sacl.Render(); flags |= SECURITY_DESCRIPTOR_CONTROL.SE_SACL_PRESENT; } else { flags |= SECURITY_DESCRIPTOR_CONTROL.SE_SACL_PROTECTED; } Marshal.WriteIntPtr(ptr + 4 + IntPtr.Size * 2, pSacl.GetValueOrDefault(IntPtr.Zero)); if (dacl != null) { pDacl = dacl.Render(); flags |= SECURITY_DESCRIPTOR_CONTROL.SE_DACL_PRESENT; } else { flags |= SECURITY_DESCRIPTOR_CONTROL.SE_DACL_PROTECTED; } Marshal.WriteIntPtr(ptr + 4 + IntPtr.Size * 3, pDacl.GetValueOrDefault(IntPtr.Zero)); } catch { if (pSidOwner != null && pSidOwner != IntPtr.Zero) { Marshal.FreeHGlobal((IntPtr)pSidOwner); } if (pSidGroup != null && pSidGroup != IntPtr.Zero) { Marshal.FreeHGlobal((IntPtr)pSidGroup); } if (pSacl != null && pSacl != IntPtr.Zero) { Marshal.FreeHGlobal((IntPtr)pSacl); } if (pDacl != null && pDacl != IntPtr.Zero) { Marshal.FreeHGlobal((IntPtr)pDacl); } throw; } return ptr; } public void Dispose() { if (disposed) { return; } disposed = true; FreeSecurityDescriptor(); } public SecurityDescriptor( IntPtr pSecurityDescriptor, bool shouldBeFreed = false, IntPtr? pSidOwner = null, IntPtr? pSidGroup = null, IntPtr? pSacl = null, IntPtr? pDacl = null ) { this.pSecurityDescriptor = pSecurityDescriptor; SECURITY_DESCRIPTOR_CONTROL control = (SECURITY_DESCRIPTOR_CONTROL)(ushort)Marshal.ReadInt16(pSecurityDescriptor, 2); this.shouldBeFreed = shouldBeFreed; this.pSidOwner = pSidOwner; this.pSidGroup = pSidGroup; this.pSacl = pSacl; this.pDacl = pDacl; ownerDefaulted = (control & SECURITY_DESCRIPTOR_CONTROL.SE_OWNER_DEFAULTED) != 0; groupDefaulted = (control & SECURITY_DESCRIPTOR_CONTROL.SE_GROUP_DEFAULTED) != 0; saclDefaulted = (control & SECURITY_DESCRIPTOR_CONTROL.SE_SACL_DEFAULTED) != 0; daclDefaulted = (control & SECURITY_DESCRIPTOR_CONTROL.SE_DACL_DEFAULTED) != 0; } public SecurityDescriptor( string owner, string group, IACL sacl, IACL dacl ) { Owner = owner; Group = group; Sacl = sacl; Dacl = dacl; } } [DllImport("advapi32.dll", EntryPoint="GetSecurityInfo", SetLastError=true)] public static extern uint _GetSecurityInfo( IntPtr handle, SE_OBJECT_TYPE objectType, SECURITY_INFORMATION securityInfo, out IntPtr pSidOwner, out IntPtr pSidGroup, out IntPtr pDacl, // beware the order! this is opposite of SECURITY_DESCRIPTOR out IntPtr pSacl, // beware the order! this is opposite of SECURITY_DESCRIPTOR out IntPtr pSecurityDescriptor ); public static SecurityDescriptor GetSecurityInfo(IntPtr handle, SE_OBJECT_TYPE objectType, SECURITY_INFORMATION securityInfo) { IntPtr sidOwner, sidGroup, dacl, sacl, securityDescriptor; uint err = _GetSecurityInfo( handle, objectType, securityInfo, out sidOwner, out sidGroup, out dacl, out sacl, out securityDescriptor ); if (0 != err) { throw new Win32APIException((int)err); } return new SecurityDescriptor( securityDescriptor, true, (securityInfo & SECURITY_INFORMATION.OWNER) != 0 ? (IntPtr?)sidOwner: (IntPtr?)null, (securityInfo & SECURITY_INFORMATION.GROUP) != 0 ? (IntPtr?)sidGroup: (IntPtr?)null, (securityInfo & SECURITY_INFORMATION.SACL) != 0 ? (IntPtr?)sacl: (IntPtr?)null, (securityInfo & SECURITY_INFORMATION.DACL) != 0 ? (IntPtr?)dacl: (IntPtr?)null ); } [DllImport("advapi32.dll", EntryPoint="SetSecurityInfo", SetLastError=true)] public static extern uint _SetSecurityInfo( IntPtr handle, SE_OBJECT_TYPE objectType, SECURITY_INFORMATION securityInfo, IntPtr pSidOwner, IntPtr pSidGroup, IntPtr pDacl, // beware the order! this is opposite of SECURITY_DESCRIPTOR IntPtr pSacl // beware the order! this is opposite of SECURITY_DESCRIPTOR ); public static void SetSecurityInfo(IntPtr handle, SE_OBJECT_TYPE objectType, SECURITY_INFORMATION securityInfo, SecurityDescriptor desc) { uint err = _SetSecurityInfo( handle, objectType, securityInfo, desc.PSidOwner.GetValueOrDefault(IntPtr.Zero), desc.PSidGroup.GetValueOrDefault(IntPtr.Zero), desc.PDacl.GetValueOrDefault(IntPtr.Zero), desc.PSacl.GetValueOrDefault(IntPtr.Zero) ); if (0 != err) { throw new Win32APIException((int)err); } } public enum TOKEN_INFORMATION_CLASS { TokenUser = 1, TokenGroups, TokenPrivileges, TokenOwner, TokenPrimaryGroup, TokenDefaultDacl, TokenSource, TokenType, TokenImpersonationLevel, TokenStatistics, TokenRestrictedSids, TokenSessionId, TokenGroupsAndPrivileges, TokenSessionReference, TokenSandBoxInert, TokenAuditPolicy, TokenOrigin, TokenElevationType, TokenLinkedToken, TokenElevation, TokenHasRestrictions, TokenAccessInformation, TokenVirtualizationAllowed, TokenVirtualizationEnabled, TokenIntegrityLevel, TokenUIAccess, TokenMandatoryPolicy, TokenLogonSid, TokenIsAppContainer, TokenCapabilities, TokenAppContainerSid, TokenAppContainerNumber, TokenUserClaimAttributes, TokenDeviceClaimAttributes, TokenRestrictedUserClaimAttributes, TokenRestrictedDeviceClaimAttributes, TokenDeviceGroups, TokenRestrictedDeviceGroups, TokenSecurityAttributes, TokenIsRestricted, MaxTokenInfoClass } [DllImport("advapi32.dll", EntryPoint="GetTokenInformation", SetLastError=true)] public static extern bool _GetTokenInformation( IntPtr tokenHandle, TOKEN_INFORMATION_CLASS tokenInformationClass, IntPtr tokenInformation, uint tokenInformationLength, out uint returnLength ); public static void GetTokenInformation( IntPtr tokenHandle, TOKEN_INFORMATION_CLASS tokenInformationClass, IntPtr tokenInformation, uint tokenInformationLength, out uint returnLength ) { if (!_GetTokenInformation( tokenHandle, tokenInformationClass, tokenInformation, tokenInformationLength, out returnLength)) { throw new Win32APIException(Marshal.GetLastWin32Error()); } } public static IntPtr GetTokenInformation( IntPtr tokenHandle, TOKEN_INFORMATION_CLASS tokenInformationClass ) { uint returnLength = 0; _GetTokenInformation(tokenHandle, tokenInformationClass, IntPtr.Zero, 0, out returnLength); IntPtr buf = Marshal.AllocHGlobal((int)returnLength); try { GetTokenInformation(tokenHandle, tokenInformationClass, buf, returnLength, out returnLength); } catch { Marshal.FreeHGlobal(buf); throw; } return buf; } public struct _SID_AND_ATTRIBUTES { IntPtr Sid; uint Attributes; } public static string GetTokenUser(IntPtr tokenHandle, out uint attributes) { IntPtr buf = GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenUser); try { IntPtr pSid = Marshal.ReadIntPtr(buf, 0); attributes = (uint)Marshal.ReadInt32(buf, IntPtr.Size); return ConvertSidToStringSid(pSid); } finally { Marshal.FreeHGlobal(buf); } } [DllImport("advapi32.dll", EntryPoint="OpenProcessToken", SetLastError=true)] public static extern bool _OpenProcessToken( IntPtr processHandle, ACCESS_MASK desiredAccess, out IntPtr tokenHandle ); public static IntPtr OpenProcessToken(IntPtr processHandle, ACCESS_MASK desiredAccess) { IntPtr retval; if (!_OpenProcessToken(processHandle, desiredAccess, out retval)) { throw new Win32APIException(Marshal.GetLastWin32Error()); } return retval; } } public sealed class PSAPI { [DllImport("psapi.dll", EntryPoint="GetProcessImageFileNameW", SetLastError=true)] public static extern uint _GetProcessImageFileName(IntPtr hProcess, IntPtr lpImageFileName, uint nSize); public static string GetProcessImageFileName(IntPtr hProcess) { IntPtr buf = Marshal.AllocHGlobal(260); try { uint len = _GetProcessImageFileName(hProcess, buf, 260); return Marshal.PtrToStringUni(buf, (int)len); } finally { Marshal.FreeHGlobal(buf); } } } } // vim: sts=4 ts=4 sw=4 et |