[return: MarshalAs(UnmanagedType.Bool)]\r
static extern bool GetExitCodeProcess(IntPtr hProcess, out int lpExitCode);\r
\r
+ #region 権限降格関連\r
+ \r
+ [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError=true)]\r
+ [return: MarshalAs(UnmanagedType.Bool)]\r
+ static extern bool CreateProcessWithTokenW(\r
+ IntPtr hToken,\r
+ uint dwLogonFlags,\r
+ string lpApplicationName, string lpCommandLine,\r
+ uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory,\r
+ [In] ref STARTUPINFO lpStartupInfo,\r
+ out PROCESS_INFORMATION lpProcessInfo);\r
+\r
+ // For Windows Mobile, replace user32.dll with coredll.dll\r
+ [DllImport("user32.dll", SetLastError = true)]\r
+ static extern IntPtr FindWindow(string lpClassName, string lpWindowName);\r
+ \r
+ [DllImport("user32.dll", SetLastError=true)]\r
+ static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);\r
+ \r
+ [DllImport("advapi32.dll", SetLastError=true)]\r
+ [return: MarshalAs(UnmanagedType.Bool)]\r
+ static extern bool OpenProcessToken(IntPtr ProcessHandle, uint DesiredAccess, out IntPtr TokenHandle);\r
+ \r
+ [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]\r
+ extern static bool DuplicateTokenEx(\r
+ IntPtr hExistingToken,\r
+ uint dwDesiredAccess,\r
+ /* ref SECURITY_ATTRIBUTES lpTokenAttributes, */\r
+ IntPtr lpTokenAttributes,\r
+ /* SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, */\r
+ uint ImpersonationLevel,\r
+ /* TOKEN_TYPE TokenType, */\r
+ uint TokenType,\r
+ out IntPtr phNewToken );\r
+ \r
+ [DllImport("kernel32.dll")]\r
+ static extern IntPtr GetEnvironmentStrings();\r
+\r
+ [DllImport("kernel32.dll")]\r
+ static extern bool FreeEnvironmentStrings(IntPtr lpszEnvironmentBlock);\r
+ \r
+ #endregion\r
+ \r
#endregion\r
\r
STARTUPINFO si;\r
/// <param name="procInfo">プロセス起動情報。\r
/// なお、<code>procInfo.UseShellExecute</code>は必ずfalseでなければならない</param>\r
public CreateProcessCaller(ProcessStartInfo procInfo)\r
+ : this(procInfo, false)\r
+ {\r
+ }\r
+ \r
+ public CreateProcessCaller(ProcessStartInfo procInfo, bool runAsNormalUser)\r
{\r
if (procInfo.UseShellExecute) {\r
throw new ArgumentException("UseShellExecute must be false");\r
if (procInfo.CreateNoWindow) dwCreationFlags |= 0x08000000; // CREATE_NO_WINDOW\r
string lpCurrentDirectory = (System.IO.Directory.Exists(procInfo.WorkingDirectory))? procInfo.WorkingDirectory : null;\r
\r
- bool retValue = CreateProcess(lpFileName, procInfo.Arguments,\r
+ bool retValue;\r
+ if (runAsNormalUser && NaGet.Utils.IsAdministrators()) {\r
+ retValue = _CreateProcessAsNormalUser(lpFileName, procInfo.Arguments,\r
IntPtr.Zero, IntPtr.Zero,\r
false, dwCreationFlags,\r
IntPtr.Zero, lpCurrentDirectory, ref si, out pi);\r
+ } else {\r
+ retValue = CreateProcess(lpFileName, procInfo.Arguments,\r
+ IntPtr.Zero, IntPtr.Zero,\r
+ false, dwCreationFlags,\r
+ IntPtr.Zero, lpCurrentDirectory, ref si, out pi);\r
+ }\r
+ \r
if (! retValue) {\r
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());\r
}\r
- CloseHandle(pi.hThread);\r
+ if (pi.hThread != IntPtr.Zero) {\r
+ CloseHandle(pi.hThread);\r
+ }\r
+ }\r
+ \r
+ private bool _CreateProcessAsNormalUser(string lpApplicationName,\r
+ string lpCommandLine,\r
+ /* ref SECURITY_ATTRIBUTES lpProcessAttributes, */\r
+ IntPtr lpProcessAttributes,\r
+ /* ref SECURITY_ATTRIBUTES lpThreadAttributes, */\r
+ IntPtr lpThreadAttributes,\r
+ bool bInheritHandles,\r
+ uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory,\r
+ [In] ref STARTUPINFO lpStartupInfo,\r
+ out PROCESS_INFORMATION lpProcessInformation)\r
+ {\r
+ /*\r
+ * cf. nsWindowsRestart.cpp#LaunchAsNormalUser\r
+ * 動作チェックせず\r
+ */\r
+ \r
+ \r
+ lpProcessInformation = new PROCESS_INFORMATION(); /* fake */\r
+ try {\r
+ IntPtr hwndShell = FindWindow("Progman", null);\r
+ uint dwProcessId;\r
+ GetWindowThreadProcessId(hwndShell, out dwProcessId);\r
+ Process procShell = Process.GetProcessById((int) dwProcessId);\r
+ if (procShell == null) {\r
+ return false;\r
+ }\r
+ \r
+ IntPtr hTokenHandle, hNewToken;\r
+ // bool ok = OpenProcessToken(hProcessShell, MAXIMUM_ALLOWED, out hTokenHandle);\r
+ bool ok = OpenProcessToken(procShell.Handle, 0x02000000, out hTokenHandle);\r
+ if (!ok) return false;\r
+ // ok = DuplicateTokenEx(hTokenShell, MAXIMUM_ALLOWED, null, SecurityDelegation, TokenPrimary, out hNewToken);\r
+ ok = DuplicateTokenEx(hTokenHandle, 0x02000000, IntPtr.Zero, 3, 1, out hNewToken);\r
+ CloseHandle(hTokenHandle);\r
+ if (!ok) return false;\r
+\r
+ IntPtr myenv = GetEnvironmentStrings();\r
+ ok = CreateProcessWithTokenW(hNewToken,\r
+ 0, // profile is already loaded\r
+ lpApplicationName,\r
+ lpCommandLine,\r
+ dwCreationFlags,\r
+ myenv,\r
+ lpCurrentDirectory,\r
+ ref lpStartupInfo,\r
+ out lpProcessInformation);\r
+ if (myenv != IntPtr.Zero) {\r
+ FreeEnvironmentStrings(myenv);\r
+ }\r
+ CloseHandle(hNewToken);\r
+ \r
+ return ok;\r
+ } catch {\r
+ return false;\r
+ }\r
}\r
\r
/// <summary>\r
/// </summary>\r
public void Dispose()\r
{\r
- CloseHandle(pi.hProcess);\r
+ if (pi.hProcess != IntPtr.Zero) {\r
+ CloseHandle(pi.hProcess);\r
+ }\r
}\r
\r
}\r