/// <summary> /// Return the process SID, if it can be obtained. Otherwise, an empty string /// is returned. /// </summary> public static String GetProcessSid(Process p) { IntPtr procTokenHandle = IntPtr.Zero; IntPtr pSid = IntPtr.Zero; String strSID = ""; IntPtr tokenInfo = IntPtr.Zero; Syscalls.TOKEN_USER userToken; int tokenInfoLength = 0; try { // Open the process in order to fill out procToken. if (!Syscalls.OpenProcessToken(p.Handle, Syscalls.TOKEN_QUERY, ref procTokenHandle)) { throw Syscalls.LastErrorException(); } // Get the required buffer size by making a first call that will // fail, then allocate tokenInfo accordingly and make the call again. if (!Syscalls.GetTokenInformation( procTokenHandle, Syscalls.TOKEN_INFORMATION_CLASS.TokenUser, tokenInfo, 0, ref tokenInfoLength)) { // ERROR_INSUFFICIENT_BUFFER is expected. Fail on anything else. if (Syscalls.GetLastError() != Syscalls.ERROR_INSUFFICIENT_BUFFER) { throw Syscalls.LastErrorException(); } } // Allocate the right buffer, now that we know the requried size. tokenInfo = Marshal.AllocHGlobal(tokenInfoLength); // Make the real call. if (!Syscalls.GetTokenInformation( procTokenHandle, Syscalls.TOKEN_INFORMATION_CLASS.TokenUser, tokenInfo, tokenInfoLength, ref tokenInfoLength)) { throw Syscalls.LastErrorException(); } userToken = (Syscalls.TOKEN_USER)Marshal.PtrToStructure(tokenInfo, typeof(Syscalls.TOKEN_USER)); pSid = userToken.User.Sid; Syscalls.ConvertSidToStringSid(pSid, ref strSID); return(strSID); } catch (Exception ex) { Logging.LogException(ex); return(""); } finally { if (procTokenHandle != IntPtr.Zero) { Syscalls.CloseHandle(procTokenHandle); } if (tokenInfo != IntPtr.Zero) { Marshal.FreeHGlobal(tokenInfo); } } }