I can't use System.Diagnostics.Process in my case since this class ALWAYS
creates the process with the underlying process security context, not the
impersonated users security context.
This code is being executed within a ASP.NET web services.
The following is the function that is being called. When the executable
parameter passed in is a batch file, I get the 'Access Denied' error on
the
CreateProcessAsUser call. If the executable parameter is a program, then
everything works nicely. As stated in earlier Threads, both the batch
file
and the program file are in the same directory and the impersonated user
has
Full rights.
<<**********************************
#region Win32 declarations
[StructLayout(LayoutKind.Sequential)]
private struct STARTUPINFO
{
public int cb;
public String lpReserved;
public String lpDesktop;
public String lpTitle;
public uint dwX;
public uint dwY;
public uint dwXSize;
public uint dwYSize;
public uint dwXCountChars;
public uint dwYCountChars;
public uint dwFillAttribute;
public uint dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
private struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public uint dwProcessId;
public uint dwThreadId;
}
[StructLayout(LayoutKind.Sequential)]
private struct SECURITY_ATTRIBUTES
{
public int Length;
public IntPtr lpSecurityDescriptor;
public bool bInheritHandle;
}
[DllImport("kernel32.dll")]
private static extern bool GetExitCodeProcess(IntPtr hProcess, out uint
lpExitCode);
[DllImport("kernel32", SetLastError=true, ExactSpelling=true)]
private static extern Int32 WaitForSingleObject(IntPtr handle, Int32
milliseconds);
[DllImport("kernel32.dll", EntryPoint="CloseHandle", SetLastError=true,
CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
private extern static bool CloseHandle(IntPtr handle);
[DllImport("advapi32.dll", EntryPoint="CreateProcessAsUser",
SetLastError=true, CharSet=CharSet.Ansi,
CallingConvention=CallingConvention.StdCall)]
private extern static bool CreateProcessAsUser(IntPtr hToken, String
lpApplicationName, String lpCommandLine, ref SECURITY_ATTRIBUTES
lpProcessAttributes,
ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandle, int
dwCreationFlags, IntPtr lpEnvironment,
String lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out
PROCESS_INFORMATION lpProcessInformation);
[DllImport("advapi32.dll", EntryPoint="DuplicateTokenEx",
SetLastError=true)]
private extern static bool DuplicateTokenEx(IntPtr ExistingTokenHandle,
uint dwDesiredAccess,
ref SECURITY_ATTRIBUTES lpThreadAttributes, int TokenType,
int ImpersonationLevel, ref IntPtr DuplicateTokenHandle);
#endregion
public static int RunProcessAsUser(string executable,string cmdLine,int
timeOut)
{
int errorCode = 0;
bool ret;
IntPtr token = new IntPtr(0);
IntPtr dupedToken = new IntPtr(0);
SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
sa.bInheritHandle = false;
sa.Length = Marshal.SizeOf(sa);
sa.lpSecurityDescriptor = (IntPtr)0;
token = WindowsIdentity.GetCurrent().Token;
const uint GENERIC_ALL = 0x10000000;
const int SecurityImpersonation = 2;
const int TokenType = 1;
ret = DuplicateTokenEx(token, GENERIC_ALL, ref sa,
SecurityImpersonation,
TokenType, ref dupedToken);
if (ret == false)
{
errorCode = Marshal.GetLastWin32Error();
throw new Exceptions.SecurityException("Unable to duplicate User
Security Token",new Win32Exception(errorCode));
}
STARTUPINFO si = new STARTUPINFO();
si.cb = Marshal.SizeOf(si);
si.lpDesktop = "";
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
ret = CreateProcessAsUser(dupedToken, executable, cmdLine, ref sa, ref
sa, false, 0, (IntPtr)0, null, ref si, out pi);
if (ret == false)
{
errorCode = Marshal.GetLastWin32Error();
throw new Exceptions.SecurityException("Unable to Create Process for
User",new Win32Exception(errorCode));
}
if(WaitForSingleObject( pi.hProcess, timeOut ) != 0)
throw new Exceptions.WarningException("Timeout running User
Process");
uint ec;
GetExitCodeProcess(pi.hProcess,out ec);
errorCode = (int)ec;
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
CloseHandle(dupedToken);
return errorCode;
}
**********************************>>
Yunus Emre ALPÖZEN said:
do u develop an ASP.NET web service ???
"CreateProcessAsUser property specifies whether a CGI process is created
in
the system context or in the context of the requesting user"
not a batch application.
My advice u to use System.Diagnostics.Process...
Do u have any sample code to cause error again??