Solved

Need help in studying this c# class

Posted on 2006-11-01
3
932 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
ID: 17848816
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
ID: 17848846
0
 
LVL 5

Expert Comment

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

Featured Post

Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction When many people think of the WebBrowser (http://msdn.microsoft.com/en-us/library/2te2y1x6%28v=VS.85%29.aspx) control, they immediately think of a control which allows the viewing and navigation of web pages. While this is true, it's a…
Microsoft Reports are based on a report definition, which is an XML file that describes data and layout for the report, with a different extension. You can create a client-side report definition language (*.rdlc) file with Visual Studio, and build g…
This video shows how to use Hyena, from SystemTools Software, to bulk import 100 user accounts from an external text file. View in 1080p for best video quality.
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…

776 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