1: /// <summary>
2: /// Defines the shutdown mode
3: /// </summary>
4: public enum ShutDownMode {
5: /// <summary>
6: /// Log off current user.
7: /// </summary>
8: LogOff = 0,
9: /// <summary>
10: /// Shut down computer without turning power off (some OS's still power off though)
11: /// </summary>
12: ShutDown = 0x1,
13: /// <summary>
14: /// Shut down computer and turn power off if supported.
15: /// </summary>
16: ShutDownAndPowerOff = 0x8,
17: /// <summary>
18: /// Reboot system.
19: /// </summary>
20: Reboot = 0x2,
21: /// <summary>
22: /// Reboot system and restart all applications that used RegisterApplicationRestart
23: /// to register for re-start.s
24: /// </summary>
25: RebootAndRestartApps = 0x40
26: }
27:
28: /// <summary>
29: ///
30: /// </summary>
31: public enum ForceType {
32: /// <summary>
33: /// Applications get the chance to notify the user of the upcoming shutdown.
34: /// This way the user may save changes.
35: /// </summary>
36: None = 0,
37: /// <summary>
38: /// Applications get the chance to let the user save changes. After a time-out
39: /// the applications are still forced to shutdown.
40: /// </summary>
41: ForceIfHung = 0x10,
42: /// <summary>
43: /// The user does not get a chance to save changes.
44: /// </summary>
45: Force = 0x4
46: }
47:
48: /// <summary>
49: /// Utility class to exit windows or the current interactive logon session.
50: /// </summary>
51: public static class ShutdownUtil {
52: #region Error messages
53: private const string ErrorLookupPrivilegeValue = "Konnte die Privilegdaten nicht anfordern.";
54: private const string ErrorOpenProcessToken = "Konnte token nicht öffnen";
55: private const string ErrorAdjustTokenPrivileges = "Du hast nicht die Rechte, um den Computer herunterzufahren.";
56: #endregion
57:
58: /// <summary>
59: /// Exits windows or logs off the current user
60: /// </summary>
61: /// <param name="mode">The shutdown mode.</param>
62: /// <param name="forceType">Defines whether and how a shutdown is forced.</param>
63: /// <returns><c>true</c> if shutdown was initiated; otherwise, <c>false</c></returns>
64: public static bool Shutdown( ShutDownMode mode, ForceType forceType ) {
65: IntPtr privileges = SetPrivileges();
66:
67: try {
68: uint flags = (uint)mode | (uint)forceType;
69: // Reason for shutdown (for simplicity)
70: // "Other (Planned)"
71: // SHTDN_REASON_MAJOR_OTHER |
72: // SHTDN_REASON_MINOR_OTHER |
73: // SHTDN_REASON_FLAG_PLANNED:
74: const uint PlannedShutdown = 0x80000000;
75:
76: if ( !ExitWindowsEx( flags, PlannedShutdown ) ) {
77: Console.WriteLine( Marshal.GetLastWin32Error() );
78: return false;
79: }
80: return true;
81: } finally {
82: CloseHandle( privileges );
83: }
84: }
85:
86: private static IntPtr SetPrivileges() {
87: TokenPrivileges priv = new TokenPrivileges();
88: priv.PrivilegesCount = 1;
89: priv.Privileges = new LuidAndAttributes[priv.PrivilegesCount];
90: // Get
91: if ( !LookupPrivilegeValue( "", "SeShutdownPrivilege", out priv.Privileges[ 0 ] ) ) {
92: throw new Exception( ErrorLookupPrivilegeValue );
93: }
94: priv.Privileges[ 0 ].Attributes = SE_PRIVILEGE_ENABLED;
95:
96: TokenPrivileges rec = new TokenPrivileges();
97:
98: IntPtr token;
99: IntPtr procHandle = Process.GetCurrentProcess().Handle;
100: if ( !OpenProcessToken( procHandle, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, out token ) ) {
101: throw new Exception( ErrorOpenProcessToken );
102: }
103: try {
104: int recSize;
105: if ( !AdjustTokenPrivileges( token, false, ref priv,
106: Marshal.SizeOf( rec ), ref rec, out recSize ) ||
107: Marshal.GetLastWin32Error() == 1300 /*ERROR_NOT_ALL_ASSIGNED*/ ) {
108: throw new Exception( ErrorAdjustTokenPrivileges );
109: }
110: return token;
111: } catch {
112: CloseHandle( token );
113: throw;
114: }
115: }
116:
117: #region Interop
118: [DllImport( "user32.dll" )]
119: private static extern bool ExitWindowsEx( uint mode, uint reason );
120:
121: // enable privilege on token
122: private const uint SE_PRIVILEGE_ENABLED = 2;
123: // used by OpenProcessToken
124: private const uint TOKEN_QUERY = 0x0008;
125: // used by OpenProcessToken
126: internal const uint TOKEN_ADJUST_PRIVILEGES = 0x0020;
127:
128:
129: [DllImport( "Advapi32.dll" )]
130: private static extern bool LookupPrivilegeValue( string system,
131: string privilege,
132: out LuidAndAttributes result );
133:
134: [DllImport( "advapi32.dll" )]
135: [return : MarshalAs( UnmanagedType.Bool )]
136: private static extern bool OpenProcessToken( IntPtr ProcessHandle,
137: UInt32 DesiredAccess,
138: out IntPtr TokenHandle );
139:
140: [DllImport( "Advapi32.dll" )]
141: private static extern bool AdjustTokenPrivileges( IntPtr handle,
142: bool disableAll,
143: ref TokenPrivileges newState,
144: int bufferLength,
145: ref TokenPrivileges realState,
146: out int foo );
147:
148: [DllImport( "Kernel32.dll" )]
149: private static extern bool CloseHandle( IntPtr handle );
150:
151: #region Nested type: LuidAndAttributes
152: [StructLayout( LayoutKind.Sequential )]
153: public struct LuidAndAttributes {
154: public long LUID;
155: public uint Attributes;
156: }
157: #endregion
158:
159: #region Nested type: TokenPrivileges
160: [StructLayout( LayoutKind.Sequential )]
161: private struct TokenPrivileges {
162: public uint PrivilegesCount;
163: [MarshalAs( UnmanagedType.ByValArray, SizeConst = 1 )]
164: public LuidAndAttributes[] Privileges;
165: }
166: #endregion
167:
168: #endregion
169: }