Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Need help in studying this c# class

Posted on 2006-11-01
3
Medium Priority
?
968 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
3 Comments
 
LVL 5

Accepted Solution

by:
DEEPESH earned 2000 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

On Demand Webinar: Networking for the Cloud Era

Did you know SD-WANs can improve network connectivity? Check out this webinar to learn how an SD-WAN simplified, one-click tool can help you migrate and manage data in the cloud.

Question has a verified solution.

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

Well, all of us have seen the multiple EXCEL.EXE's in task manager that won't die even if you call the .close, .dispose methods. Try this method to kill any excels in memory. You can copy the kill function to create a check function and replace the …
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
Want to learn how to record your desktop screen without having to use an outside camera. Click on this video and learn how to use the cool google extension called "Screencastify"! Step 1: Open a new google tab Step 2: Go to the left hand upper corn…
We’ve all felt that sense of false security before—locking down external access to a database or component and feeling like we’ve done all we need to do to secure company data. But that feeling is fleeting. Attacks these days can happen in many w…
Suggested Courses

664 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