Solved

Need help in studying this c# class

Posted on 2006-11-01
3
921 Views
Last Modified: 2012-06-27
hi, i got this class from the web. i think it enables a program to execute external application using windows Administrator(or others) account. but as a beginner, its too much for me to grasp. i need to know how to use this class?
basically i want to execute a program as administrator, and let it run without waiting for it to exit.




using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Security.Principal;
using System.Text;

///
/// UserSpecificProcess extends the standard Process object to
/// create new processes under a different user than the calling parent process.
/// Also, the standard output of the child process redirected back to the parent process.
/// This is class is designed to operate inside an ASP.NET web application.
/// The assumption is that the calling thread is operating with an impersonated security token.
/// The this class will change the imperonated security token to a primary token,
/// and call CreateProcessAsUser.
/// A System.Diagnostics.Process object will be returned with appropriate properties set.
/// To use this function, the following security priviliges need to be set for the ASPNET account
/// using the local security policy MMC snap-in. CreateProcessAsUser requirement.
/// "Replace a process level token"/SE_ASSIGNPRIMARYTOKEN_NAME/SeAssignPrimaryTokenPrivilege
/// "Adjust memory quotas for a process"/SE_INCREASE_QUOTA_NAME/SeIncreaseQuotaPrivilege
///
/// This class was designed for .NET 1.1 for operating systems W2k an higher.
/// Any other features or platform support can be implemented by using the .NET reflector and
/// investigating the Process class.
///
public class UserSpecificProcess : Process
{
    [StructLayout(LayoutKind.Sequential)]
    public class CreateProcessStartupInfo
    {
        public int cb;
        public string 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 int dwFlags;
        public short wShowWindow;
        public short cbReserved2;
        public IntPtr lpReserved2;
        public IntPtr hStdInput;
        public IntPtr hStdOutput;
        public IntPtr hStdError;
        public CreateProcessStartupInfo()
        {
            this.cb = Marshal.SizeOf(typeof(CreateProcessStartupInfo));
            this.lpReserved = null;
            this.lpDesktop = null;
            this.lpTitle = null;
            this.dwX = 0;
            this.dwY = 0;
            this.dwXSize = 0;
            this.dwYSize = 0;
            this.dwXCountChars = 0;
            this.dwYCountChars = 0;
            this.dwFillAttribute = 0;
            this.dwFlags = 0;
            this.wShowWindow = 0;
            this.cbReserved2 = 0;
            this.lpReserved2 = IntPtr.Zero;
            this.hStdInput = IntPtr.Zero;
            this.hStdOutput = IntPtr.Zero;
            this.hStdError = IntPtr.Zero;
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    public class CreateProcessProcessInformation
    {
        public IntPtr hProcess;
        public IntPtr hThread;
        public int dwProcessId;
        public int dwThreadId;
        public CreateProcessProcessInformation()
        {
            this.hProcess = IntPtr.Zero;
            this.hThread = IntPtr.Zero;
            this.dwProcessId = 0;
            this.dwThreadId = 0;
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    public class SecurityAttributes
    {
        public int nLength;
        public IntPtr lpSecurityDescriptor;
        public bool bInheritHandle;
        public SecurityAttributes()
        {
            this.nLength = Marshal.SizeOf(typeof(SecurityAttributes));
        }
    }

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
    public static extern bool CloseHandle(HandleRef handle);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool CreateProcess([MarshalAs(UnmanagedType.LPTStr)] string lpApplicationName, StringBuilder lpCommandLine, SecurityAttributes lpProcessAttributes, SecurityAttributes lpThreadAttributes, bool bInheritHandles, int dwCreationFlags, IntPtr lpEnvironment, [MarshalAs(UnmanagedType.LPTStr)] string lpCurrentDirectory, CreateProcessStartupInfo lpStartupInfo, CreateProcessProcessInformation lpProcessInformation);

    [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern bool CreateProcessAsUserW(IntPtr token, [MarshalAs(UnmanagedType.LPTStr)] string lpApplicationName, [MarshalAs(UnmanagedType.LPTStr)] string lpCommandLine, SecurityAttributes lpProcessAttributes, SecurityAttributes lpThreadAttributes, bool bInheritHandles, int dwCreationFlags, IntPtr lpEnvironment, [MarshalAs(UnmanagedType.LPTStr)] string lpCurrentDirectory, CreateProcessStartupInfo lpStartupInfo, CreateProcessProcessInformation lpProcessInformation);

    [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
    public static extern IntPtr GetStdHandle(int whichHandle);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr CreateFile(string lpFileName, int dwDesiredAccess, int dwShareMode, SecurityAttributes lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, HandleRef hTemplateFile);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern IntPtr CreateNamedPipe(string name, int openMode, int pipeMode, int maxInstances, int outBufSize, int inBufSize, int timeout, SecurityAttributes lpPipeAttributes);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern int GetConsoleOutputCP();

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool DuplicateTokenEx(HandleRef hToken, int access, SecurityAttributes tokenAttributes, int impersonationLevel, int tokenType, ref IntPtr hNewToken);

    // WinNT.h ACCESS TYPES
    const int GENERIC_ALL = 0x10000000;

    // WinNT.h enum SECURITY_IMPERSONATION_LEVEL
    const int SECURITY_IMPERSONATION = 2;

    // WinNT.h TOKEN TYPE
    const int TOKEN_PRIMARY = 1;

    // WinBase.h
    const int STD_INPUT_HANDLE = -10;
    const int STD_ERROR_HANDLE = -12;

    // WinBase.h STARTUPINFO
    const int STARTF_USESTDHANDLES = 0x100;

    // Microsoft.Win23.NativeMethods
    static IntPtr INVALID_HANDLE_VALUE = (IntPtr)(-1);
    public static HandleRef NullHandleRef = new HandleRef(null, IntPtr.Zero);

    ///
    /// Starts the process with the security token of the calling thread.
    /// If the security token has a token type of TokenImpersonation,
    /// the token will be duplicated to a primary token before calling
    /// CreateProcessAsUser.
    ///
    /// The process to start.
    public void StartAsUser()
    {
        StartAsUser(WindowsIdentity.GetCurrent().Token);
    }

    ///
    /// Starts the process with the given security token.
    /// If the security token has a token type of TokenImpersonation,
    /// the token will be duplicated to a primary token before calling
    /// CreateProcessAsUser.
    ///
    ///
    public void StartAsUser(IntPtr userToken)
    {
        if (StartInfo.UseShellExecute)
        {
            throw new InvalidOperationException("can't call this with shell execute");
        }

        // just assume that the securityToken is of TokenImpersonation and create a primary.
        IntPtr primayUserToken = CreatePrimaryToken(userToken);

        CreateProcessStartupInfo startupInfo = new CreateProcessStartupInfo();
        CreateProcessProcessInformation processInformation = new CreateProcessProcessInformation();

        IntPtr stdinHandle;
        IntPtr stdoutReadHandle;
        IntPtr stdoutWriteHandle = IntPtr.Zero;
        IntPtr stderrHandle;
        try
        {
            stdinHandle = GetStdHandle(STD_INPUT_HANDLE);
            MyCreatePipe(out stdoutReadHandle, out stdoutWriteHandle, false);
            stderrHandle = GetStdHandle(STD_ERROR_HANDLE);

            //assign handles to startup info
            startupInfo.dwFlags = STARTF_USESTDHANDLES;
            startupInfo.hStdInput = stdinHandle;
            startupInfo.hStdOutput = stdoutWriteHandle;
            startupInfo.hStdError = stderrHandle;

            string commandLine = GetCommandLine();
            int creationFlags = 0;
            IntPtr environment = IntPtr.Zero;
            string workingDirectory = GetWorkingDirectory();

            // create the process or fail trying.
            if (!CreateProcessAsUserW(
            primayUserToken,
            null,
            commandLine,
            null,
            null,
            true,
            creationFlags,
            environment,
            workingDirectory,
            startupInfo,
            processInformation))
            {
                throw new Win32Exception();
            }
        }
        finally
        {
            // close thread handle
            if (processInformation.hThread != INVALID_HANDLE_VALUE)
            {
                CloseHandle(new HandleRef(this, processInformation.hThread));
            }

            // close client stdout handle
            CloseHandle(new HandleRef(this, stdoutWriteHandle));
        }

        // get reader for standard output from the child
        Encoding encoding = Encoding.GetEncoding(GetConsoleOutputCP());
        StreamReader standardOutput = new StreamReader(new FileStream(stdoutReadHandle, FileAccess.Read, true, 0x1000, true), encoding);

        // set this on the object accordingly.
        typeof(Process).InvokeMember("standardOutput",
        BindingFlags.SetField | BindingFlags.NonPublic | BindingFlags.Instance,
        null, this, new object[] { standardOutput });

        // scream if a process wasn't started instead of returning false.
        if (processInformation.hProcess == IntPtr.Zero)
        {
            throw new Exception("failed to create process");
        }

        // configure the properties of the Process object correctly
        typeof(Process).InvokeMember("SetProcessHandle",
        BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance,
        null, this, new object[] { processInformation.hProcess });
        typeof(Process).InvokeMember("SetProcessId",
        BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance,
        null, this, new object[] { processInformation.dwProcessId });
    }

    ///
    /// Creates a primayToken out of an existing token.
    ///
    ///
    private IntPtr CreatePrimaryToken(IntPtr userToken)
    {
        SecurityAttributes securityAttributes = new SecurityAttributes();
        IntPtr primaryUserToken = IntPtr.Zero;
        if (!DuplicateTokenEx(new HandleRef(this, userToken), GENERIC_ALL, securityAttributes, SECURITY_IMPERSONATION, TOKEN_PRIMARY, ref primaryUserToken))
        {
            throw new Win32Exception();
        }
        return primaryUserToken;
    }

    ///
    /// Gets the appropriate commandLine from the process.
    ///
    ///
    ///
    private string GetCommandLine()
    {
        StringBuilder builder1 = new StringBuilder();
        string text1 = StartInfo.FileName.Trim();
        string text2 = StartInfo.Arguments;
        bool flag1 = text1.StartsWith("\"") && text1.EndsWith("\"");
        if (!flag1)
        {
            builder1.Append("\"");
        }
        builder1.Append(text1);
        if (!flag1)
        {
            builder1.Append("\"");
        }
        if ((text2 != null) && (text2.Length > 0))
        {
            builder1.Append(" ");
            builder1.Append(text2);
        }
        return builder1.ToString();
    }

    ///
    /// Gets the working directory or returns null if an empty string was found.
    ///
    ///
    private string GetWorkingDirectory()
    {
        return (StartInfo.WorkingDirectory != string.Empty) ? StartInfo.WorkingDirectory : null;
    }

    ///
    /// A clone of Process.CreatePipe. This is only implemented because reflection with
    /// out parameters are a pain.
    /// Note: This is only finished for w2k and higher machines.
    ///
    ///
    ///
    /// Specifies whether the parent will be performing the writes.
    public static void MyCreatePipe(out IntPtr parentHandle, out IntPtr childHandle, bool parentInputs)
    {
        string pipename = @"\\.\pipe\Global\" + Guid.NewGuid().ToString();

        SecurityAttributes attributes2 = new SecurityAttributes();
        attributes2.bInheritHandle = false;

        parentHandle = CreateNamedPipe(pipename, 0x40000003, 0, 0xff, 0x1000, 0x1000, 0, attributes2);
        if (parentHandle == INVALID_HANDLE_VALUE)
        {
            throw new Win32Exception();
        }

        SecurityAttributes attributes3 = new SecurityAttributes();
        attributes3.bInheritHandle = true;
        int num1 = 0x40000000;
        if (parentInputs)
        {
            num1 = -2147483648;
        }
        childHandle = CreateFile(pipename, num1, 3, attributes3, 3, 0x40000080, NullHandleRef);
        if (childHandle == INVALID_HANDLE_VALUE)
        {
            throw new Win32Exception();
        }
    }
}
0
Comment
Question by:dynamicrevolutions
  • 3
3 Comments
 
LVL 5

Accepted Solution

by:
DEEPESH earned 500 total points
Comment Utility
Explaining whole code is bit difficult but I may help you a bit

using System;
using syntax in C# is Imports keyword in Vb.Net

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] this is the way in C# to use Windows Api
In vb.net you can use it in the following manner

<DllImport("KERNEL32.DLL", EntryPoint:="GetSystemDirectoryW", _
       SetLastError:=True, CharSet:=CharSet.Unicode, _
       ExactSpelling:=True, _
       CallingConvention:=CallingConvention.StdCall)> _
       Public Shared Function GetSystemDirectory(ByVal Buffer _
         As StringBuilder, ByVal Size As Integer) As Long
        ' Leave function empty - DLLImport attribute
        ' forces calls to GetSystemDirectory to
        ' be forwarded to GetSystemDirectory in KERNEL32.DLL
    End Function

Variable declaration in C#
SecurityAttributes attributes2 = new SecurityAttributes();
in vb.Net u can use it in following manner
Dim attributes2 as new SecurityAttributes();


In last but not least, why dont you make this code as C# assembly and
use this assembly in VB.net directly by calling methods
0
 
LVL 5

Expert Comment

by:DEEPESH
Comment Utility
0
 
LVL 5

Expert Comment

by:DEEPESH
Comment Utility
Sorry i forget to mention , try this one also http://www.kamalpatel.net/ConvertCSharp2VB.aspx
0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

Article by: Kraeven
Introduction Remote Share is a simple remote sharing tool, enabling you to see, add and remove remote or local shares. The application is written in VB.NET targeting the .NET framework 2.0. The source code and the compiled programs have been in…
1.0 - Introduction Converting Visual Basic 6.0 (VB6) to Visual Basic 2008+ (VB.NET). If ever there was a subject full of murkiness and bad decisions, it is this one!   The first problem seems to be that people considering this task of converting…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now