Разница в поведении ExitWindowsEx на Windows Server 2012 R2 со стандартным пользователем - PullRequest
0 голосов
/ 10 марта 2020

Я пишу C# программу, которая вызывает ExitWindowsEx для перезагрузки компьютера. Используя код из этой ссылки , я повысил привилегию. Программа отлично работает на Windows 7 и 10, но не работает на Windows Server 2012 R2 с обычным пользователем. Если я запускаю программу от имени администратора, но система просто выходит из системы и сразу возвращается на страницу входа.

Политика безопасности завершения работы

property

Стандартный пользователь не добавлен. Этот пользователь не имеет права перезагрузки. Поэтому я не смог перезагрузиться?

Я пытался вызвать процесс shutdown.exe с правами администратора, ОС могла перезагрузиться. В чем разница между вызовом функции ExitWindowsEx и процессом запуска shutdown.exe? Прикрепите мой код:

static void RebootComputer()
{
    IntPtr tokenHandle = IntPtr.Zero;

    try
    {
        // get process token
        if (!NativeMethods.OpenProcessToken(Process.GetCurrentProcess().Handle,
            TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
            out tokenHandle))
        {
            throw new Win32Exception(Marshal.GetLastWin32Error(),
                "Failed to open process token handle");
        }

        // lookup the shutdown privilege
        NativeMethods.TOKEN_PRIVILEGES tokenPrivs = new NativeMethods.TOKEN_PRIVILEGES();
        tokenPrivs.PrivilegeCount = 1;
        tokenPrivs.Privileges = new NativeMethods.LUID_AND_ATTRIBUTES[1];
        tokenPrivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

        if (!NativeMethods.LookupPrivilegeValue(null,
            SE_SHUTDOWN_NAME,
            out tokenPrivs.Privileges[0].Luid))
        {
            throw new Win32Exception(Marshal.GetLastWin32Error(),
                "Failed to open lookup shutdown privilege");
        }

        // add the shutdown privilege to the process token
        if (!NativeMethods.AdjustTokenPrivileges(tokenHandle,
            false,
            ref tokenPrivs,
            0,
            IntPtr.Zero,
            IntPtr.Zero))
        {
            throw new Win32Exception(Marshal.GetLastWin32Error(),
                "Failed to adjust process token privileges");
        }

        // reboot
        if (!NativeMethods.ExitWindowsEx(NativeMethods.ExitWindows.ShutDown,
            NativeMethods.ShutdownReason.MajorApplication |
            NativeMethods.ShutdownReason.MinorInstallation |
            NativeMethods.ShutdownReason.FlagPlanned))
        {
            throw new Win32Exception(Marshal.GetLastWin32Error(),
                "Failed to reboot system");
        }
    }
    catch (Exception e)
    {
        WriteSystemEventLog("Failed to reboot the computer. Exception Message: 0x" + e.HResult.ToString("x")+"\r\n" + e.Message);
    }
    finally
    {
        // close the process token
        if (tokenHandle != IntPtr.Zero)
        {
            NativeMethods.CloseHandle(tokenHandle);
        }
    }
}

// call shutdown.exe works
static void Reboot()
{
    var psi = new ProcessStartInfo("shutdown", "/r /t 0");
    psi.CreateNoWindow = false;
    psi.UseShellExecute = false;
    Process.Start(psi);
}

NativeMethod:

[StructLayout(LayoutKind.Sequential)]
public struct LUID
{
    public uint LowPart;
    public int HighPart;
}

[StructLayout(LayoutKind.Sequential)]
public struct LUID_AND_ATTRIBUTES
{
    public LUID Luid;
    public uint Attributes;
}

public struct TOKEN_PRIVILEGES
{
    public uint PrivilegeCount;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
    public LUID_AND_ATTRIBUTES[] Privileges;
}

[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ExitWindowsEx(ExitWindows uFlags,
    ShutdownReason dwReason);

[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool OpenProcessToken(IntPtr ProcessHandle,
    uint DesiredAccess,
    out IntPtr TokenHandle);

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool LookupPrivilegeValue(string lpSystemName,
    string lpName,
    out LUID lpLuid);

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle(IntPtr hObject);

[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool AdjustTokenPrivileges(IntPtr TokenHandle,
    [MarshalAs(UnmanagedType.Bool)]bool DisableAllPrivileges,
    ref TOKEN_PRIVILEGES NewState,
    uint Zero,
    IntPtr Null1,
    IntPtr Null2);
...