Mega Code Archive

 
Categories / C# / Development Class
 

Create Process As User

/////////////////////////////////////////////////////////////////////////////////////////////// // //    This File is Part of the CallButler Open Source PBX (http://www.codeplex.com/callbutler // //    Copyright (c) 2005-2008, Jim Heising //    All rights reserved. // //    Redistribution and use in source and binary forms, with or without modification, //    are permitted provided that the following conditions are met: // //    * Redistributions of source code must retain the above copyright notice, //      this list of conditions and the following disclaimer. // //    * Redistributions in binary form must reproduce the above copyright notice, //      this list of conditions and the following disclaimer in the documentation and/or //      other materials provided with the distribution. // //    * Neither the name of Jim Heising nor the names of its contributors may be //      used to endorse or promote products derived from this software without specific prior //      written permission. // //    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND //    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED //    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. //    IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, //    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT //    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR //    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, //    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) //    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //    POSSIBILITY OF SUCH DAMAGE. // /////////////////////////////////////////////////////////////////////////////////////////////// using System; using System.Text; using System.Runtime.InteropServices; using System.Security.Principal; using System.Security.Permissions; namespace WOSI.Utilities {     public class ProcessUtils     {         [StructLayout(LayoutKind.Sequential)]         public struct STARTUPINFO         {             public Int32 cb;             public string lpReserved;             public string lpDesktop;             public string lpTitle;             public Int32 dwX;             public Int32 dwY;             public Int32 dwXSize;             public Int32 dwXCountChars;             public Int32 dwYCountChars;             public Int32 dwFillAttribute;             public Int32 dwFlags;             public Int16 wShowWindow;             public Int16 cbReserved2;             public IntPtr lpReserved2;             public IntPtr hStdInput;             public IntPtr hStdOutput;             public IntPtr hStdError;         }         // Declare the logon types as constants         const long LOGON32_LOGON_INTERACTIVE = 2;         const long LOGON32_LOGON_NETWORK = 3;         // Declare the logon providers as constants         const long LOGON32_PROVIDER_DEFAULT = 0;         const long LOGON32_PROVIDER_WINNT50 = 3;         const long LOGON32_PROVIDER_WINNT40 = 2;         const long LOGON32_PROVIDER_WINNT35 = 1;         [StructLayout(LayoutKind.Sequential)]         public struct PROCESS_INFORMATION         {             public IntPtr hProcess;             public IntPtr hThread;             public Int32 dwProcessID;             public Int32 dwThreadID;         }         [StructLayout(LayoutKind.Sequential)]         public struct SECURITY_ATTRIBUTES         {             public Int32 Length;             public IntPtr lpSecurityDescriptor;             public bool bInheritHandle;         }         public enum SECURITY_IMPERSONATION_LEVEL         {             SecurityAnonymous,             SecurityIdentification,             SecurityImpersonation,             SecurityDelegation         }         public enum TOKEN_TYPE         {             TokenPrimary = 1,             TokenImpersonation         }         public const int GENERIC_ALL_ACCESS = 0x10000000;         [            DllImport("kernel32.dll",               EntryPoint = "CloseHandle", SetLastError = true,               CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)         ]         public static extern bool CloseHandle(IntPtr handle);         [            DllImport("advapi32.dll",               EntryPoint = "CreateProcessAsUser", SetLastError = true,               CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)         ]         public static extern bool            CreateProcessAsUser(IntPtr hToken, string lpApplicationName, string lpCommandLine,                                ref SECURITY_ATTRIBUTES lpProcessAttributes, ref SECURITY_ATTRIBUTES lpThreadAttributes,                                bool bInheritHandle, Int32 dwCreationFlags, IntPtr lpEnvrionment,                                string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo,                                ref PROCESS_INFORMATION lpProcessInformation);         [            DllImport("advapi32.dll",               EntryPoint = "DuplicateTokenEx")         ]         public static extern bool            DuplicateTokenEx(IntPtr hExistingToken, Int32 dwDesiredAccess,                             ref SECURITY_ATTRIBUTES lpThreadAttributes,                             Int32 ImpersonationLevel, Int32 dwTokenType,                             ref IntPtr phNewToken);         [DllImport("advapi32.dll", EntryPoint = "LogonUser")]         private static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);         [DllImport("userenv.dll", CharSet = CharSet.Auto, SetLastError = true)]         private static extern bool LoadUserProfile(IntPtr hToken, ref ProfileInfo lpProfileInfo);         [DllImport("userenv.dll", SetLastError = true)]         static extern bool CreateEnvironmentBlock(out IntPtr lpEnvironment, IntPtr hToken, bool bInherit);         ///          /// Profile Info         ///          [StructLayout(LayoutKind.Sequential)]         public struct ProfileInfo         {             ///              /// Specifies the size of the structure, in bytes.             ///              public int dwSize;             ///              /// This member can be one of the following flags: PI_NOUI or PI_APPLYPOLICY             ///              public int dwFlags;             ///              /// Pointer to the name of the user.              /// This member is used as the base name of the directory in which to store a new profile.              ///              public string lpUserName;             ///              /// Pointer to the roaming user profile path.              /// If the user does not have a roaming profile, this member can be NULL.             ///              public string lpProfilePath;             ///              /// Pointer to the default user profile path. This member can be NULL.              ///              public string lpDefaultPath;             ///              /// Pointer to the name of the validating domain controller, in NetBIOS format.              /// If this member is NULL, the Windows NT 4.0-style policy will not be applied.              ///              public string lpServerName;             ///              /// Pointer to the path of the Windows NT 4.0-style policy file. This member can be NULL.              ///              public string lpPolicyPath;             ///              /// Handle to the HKEY_CURRENT_USER registry key.              ///              public IntPtr hProfile;         }          public static void CreateProcessAsUser(string username, string domain, string password, string commandLine)         {             IntPtr hToken = IntPtr.Zero;             IntPtr hDupedToken = IntPtr.Zero;                              PROCESS_INFORMATION pi = new PROCESS_INFORMATION();             try             {                 bool result = LogonUser(username, domain, password, (int)LOGON32_LOGON_INTERACTIVE, (int)LOGON32_PROVIDER_DEFAULT, ref hToken);                 if (!result)                 {                     throw new ApplicationException("LogonUser failed");                 }                 SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();                 sa.Length = Marshal.SizeOf(sa);                 result = DuplicateTokenEx(                       hToken,                       GENERIC_ALL_ACCESS,                       ref sa,                       (int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,                       (int)TOKEN_TYPE.TokenPrimary,                       ref hDupedToken                    );                 if (!result)                 {                     throw new ApplicationException("DuplicateTokenEx failed");                 }                 STARTUPINFO si = new STARTUPINFO();                 si.cb = Marshal.SizeOf(si);                 si.lpDesktop = "winsta0\\default";                 ProfileInfo info = new ProfileInfo();                 info.dwSize = Marshal.SizeOf(info);                 info.lpUserName = username;                 info.dwFlags = 1;                 result = LoadUserProfile(hDupedToken, ref info);                 if (!result)                 {                     int error = Marshal.GetLastWin32Error();                     throw new System.ComponentModel.Win32Exception(error);                 }                 IntPtr lpEnvironment;                 result = CreateEnvironmentBlock(out lpEnvironment, hDupedToken, false);                 if (!result)                 {                     int error = Marshal.GetLastWin32Error();                     throw new System.ComponentModel.Win32Exception(error);                 }                 result = CreateProcessAsUser(                                      hDupedToken,                                      null,                                      commandLine,                                      ref sa, ref sa,                                      false, 0x00000400, lpEnvironment,                                      null, ref si, ref pi                                );                 if (!result)                 {                     int error = Marshal.GetLastWin32Error();                     throw new System.ComponentModel.Win32Exception(error);                 }             }             finally             {                 if (pi.hProcess != IntPtr.Zero)                     CloseHandle(pi.hProcess);                 if (pi.hThread != IntPtr.Zero)                     CloseHandle(pi.hThread);                 if (hDupedToken != IntPtr.Zero)                     CloseHandle(hDupedToken);             }         }     } }