win-pvdrivers

view ShutdownMon/Program.cs @ 387:48df739c66d4

Removed some debugging calls to the HLT instruction
author James Harper <james.harper@bendigoit.com.au>
date Fri Jul 11 14:05:34 2008 +1000 (2008-07-11)
parents 0c6ea46f2199
children
line source
1 using System;
2 using System.Collections;
3 using System.Configuration.Install;
4 using System.ComponentModel;
5 using System.IO;
6 using System.Runtime.InteropServices;
7 using System.Reflection;
8 using System.ServiceProcess;
9 using System.Text;
10 using System.Threading;
11 using Microsoft.Win32.SafeHandles;
14 namespace ShutdownMon
15 {
16 class Program : ServiceBase
17 {
18 /*
19 * Shutdown definition see here: http://msdn2.microsoft.com/en-us/library/aa376868.aspx
20 * http://msdn2.microsoft.com/en-us/library/aa376873(VS.85).aspx
21 */
23 internal enum ShutdownReason : uint
24 {
25 MajorApplication = 0x00040000,
26 MajorHardware = 0x00010000,
27 MajorLegacyApi = 0x00070000,
28 MajorOperatingSystem = 0x00020000,
29 MajorOther = 0x00000000,
30 MajorPower = 0x00060000,
31 MajorSoftware = 0x00030000,
32 MajorSystem = 0x00050000,
34 MinorBlueScreen = 0x0000000F,
35 MinorCordUnplugged = 0x0000000b,
36 MinorDisk = 0x00000007,
37 MinorEnvironment = 0x0000000c,
38 MinorHardwareDriver = 0x0000000d,
39 MinorHotfix = 0x00000011,
40 MinorHung = 0x00000005,
41 MinorInstallation = 0x00000002,
42 MinorMaintenance = 0x00000001,
43 MinorMMC = 0x00000019,
44 MinorNetworkConnectivity = 0x00000014,
45 MinorNetworkCard = 0x00000009,
46 MinorOther = 0x00000000,
47 MinorOtherDriver = 0x0000000e,
48 MinorPowerSupply = 0x0000000a,
49 MinorProcessor = 0x00000008,
50 MinorReconfig = 0x00000004,
51 MinorSecurity = 0x00000013,
52 MinorSecurityFix = 0x00000012,
53 MinorSecurityFixUninstall = 0x00000018,
54 MinorServicePack = 0x00000010,
55 MinorServicePackUninstall = 0x00000016,
56 MinorTermSrv = 0x00000020,
57 MinorUnstable = 0x00000006,
58 MinorUpgrade = 0x00000003,
59 MinorWMI = 0x00000015,
61 FlagUserDefined = 0x40000000,
62 FlagPlanned = 0x80000000
63 }
65 const UInt32 READ_CONTROL = 0x00020000;
66 const UInt32 STANDARD_RIGHTS_READ = READ_CONTROL;
67 const UInt32 FILE_READ_DATA = 0x0001;
68 const UInt32 FILE_READ_ATTRIBUTES = 0x0080;
69 const UInt32 FILE_READ_EA = 0x0008;
70 const UInt32 SYNCHRONIZE = 0x00100000;
71 const UInt32 OPEN_EXISTING = 3;
72 const UInt32 FILE_GENERIC_READ = (STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE);
73 const UInt32 FILE_ATTRIBUTE_NORMAL = 0x0080;
75 [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
76 internal static extern SafeFileHandle CreateFile(
77 String Filename,
78 UInt32 DesiredAccess,
79 UInt32 ShareMode,
80 IntPtr Attributes,
81 UInt32 CreationDisposition,
82 UInt32 FlagsAndAttributes,
83 IntPtr TemplateFile);
85 [StructLayout(LayoutKind.Sequential, Pack = 1)]
86 internal struct TokPriv1Luid
87 {
88 public int Count;
89 public long Luid;
90 public int Attr;
91 }
93 [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
94 internal static extern IntPtr GetCurrentProcess();
96 [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
97 internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);
99 [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
100 internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);
102 [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
103 internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
105 [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
106 internal static extern bool InitiateSystemShutdownEx(string lpMachineName, string lpMessage, int dwTimeout, bool bForceAppsClosed, bool bRebootAfterShutdown, ShutdownReason dwReason);
108 // [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
110 internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
111 internal const int TOKEN_QUERY = 0x00000008;
112 internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
113 internal const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
115 [StructLayout(LayoutKind.Sequential, Pack = 1)]
116 protected struct SP_DEVICE_INTERFACE_DATA
117 {
118 public UInt32 cbSize;
119 public Guid InterfaceClassGuid;
120 public UInt32 Flags;
121 public IntPtr Reserved;
122 };
123 /*
124 [StructLayout(LayoutKind.Sequential, Pack = 1)]
125 public struct SP_DEVICE_INTERFACE_DETAIL_DATA
126 {
127 public int Size;
128 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1)]
129 public string DevicePath;
130 }
131 */
132 [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
133 private static extern IntPtr SetupDiGetClassDevsA(
134 ref Guid ClassGuid,
135 UInt32 Enumerator,
136 IntPtr hwndParent,
137 UInt32 Flags);
139 [DllImport("setupapi.dll", SetLastError = true)]
140 private static extern Boolean SetupDiEnumDeviceInterfaces(
141 IntPtr DeviceInfoSet,
142 IntPtr DeviceInfoData,
143 ref Guid InterfaceClassGuid,
144 int MemberIndex,
145 out SP_DEVICE_INTERFACE_DATA DeviceInterfaceData);
147 [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
148 private static extern Boolean SetupDiGetDeviceInterfaceDetail(
149 IntPtr DeviceInfoSet,
150 ref SP_DEVICE_INTERFACE_DATA DeviceIntefaceData,
151 IntPtr DeviceInterfaceDetailData,
152 UInt32 DeviceInterfacedetailDatasize,
153 ref UInt32 DeviceInterfacedetaildataSize,
154 IntPtr DeviceInfoData);
156 const int DIGCF_PRESENT = 0x00000002;
157 const int DIGCF_DEVICEINTERFACE = 0x00000010;
159 private string GetXenInterfacePath()
160 {
161 Guid XenInterface = new Guid("{5c568ac5-9ddf-4fa5-a94a-39d67077819c}");
162 IntPtr handle = SetupDiGetClassDevsA(ref XenInterface, 0, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
163 SP_DEVICE_INTERFACE_DATA sdid = new SP_DEVICE_INTERFACE_DATA();
165 sdid.cbSize = (UInt32)Marshal.SizeOf(sdid);
166 sdid.InterfaceClassGuid = System.Guid.Empty;
167 sdid.Flags = 0;
168 sdid.Reserved = IntPtr.Zero;
170 if (!SetupDiEnumDeviceInterfaces(handle, IntPtr.Zero, ref XenInterface, 0, out sdid))
171 throw new Win32Exception(Marshal.GetLastWin32Error());
172 Console.WriteLine("Got interface");
173 UInt32 buflen = 1024;
174 IntPtr buf = Marshal.AllocHGlobal((int)buflen);
175 if (Marshal.SizeOf(buf) == 4)
176 Marshal.WriteInt32(buf, 6); // 32 bit systems align it this way...
177 else
178 Marshal.WriteInt32(buf, 8); // and 64 bit systems align it that...
179 if (!SetupDiGetDeviceInterfaceDetail(handle, ref sdid, buf, buflen, ref buflen, IntPtr.Zero))
180 throw new Win32Exception(Marshal.GetLastWin32Error());
181 Console.WriteLine("Got detail");
182 string filename = Marshal.PtrToStringUni(new IntPtr(buf.ToInt64() + 4));
183 Console.WriteLine("interface path = " + filename);
184 // free stuff here
185 return filename;
186 }
188 private static void DoExitWin(bool bForceAppsClosed, bool bRebootAfterShutdown)
189 {
190 bool ok;
191 TokPriv1Luid tp;
192 IntPtr hproc = GetCurrentProcess();
193 IntPtr htok = IntPtr.Zero;
194 ok = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
195 tp.Count = 1;
196 tp.Luid = 0;
197 tp.Attr = SE_PRIVILEGE_ENABLED;
198 ok = LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid);
199 ok = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
200 ok = InitiateSystemShutdownEx(null, null, 0, bForceAppsClosed, bRebootAfterShutdown, ShutdownReason.MajorOther & ShutdownReason.MinorOther);
201 }
203 const string MyServiceName = "XenShutdownMon";
204 const string MyDisplayName = "Xen Shutdown Monitor Service";
205 const string MyServiceDescription = "Monitors the kernel driver and shuts down Windows when directed";
207 private static Installer MakeServiceInstaller()
208 {
209 Installer i = new Installer();
210 i.Context = new InstallContext();
211 i.Context.Parameters.Add("AssemblyPath", Assembly.GetExecutingAssembly().Location);
212 i.Context.Parameters.Add("LogToConsole", "false");
213 i.Context.Parameters.Add("Silent", "true");
215 ServiceProcessInstaller spi = new ServiceProcessInstaller();
216 spi.Account = ServiceAccount.LocalSystem;
217 spi.Username = "";
218 spi.Password = "";
219 i.Installers.Add(spi);
221 ServiceInstaller si = new ServiceInstaller();
222 si.ServiceName = MyServiceName;
223 si.DisplayName = MyDisplayName;
224 si.Description = MyServiceDescription;
225 si.StartType = ServiceStartMode.Automatic;
226 i.Installers.Add(si);
228 return i;
229 }
231 static void Main(string[] args)
232 {
233 int argNo = 0;
235 while (argNo < args.Length)
236 {
237 string arg = args[argNo++];
238 switch (arg)
239 {
240 case "-i":
241 {
242 IDictionary mySavedState = new Hashtable();
243 Installer i = MakeServiceInstaller();
244 try
245 {
246 i.Install(mySavedState);
248 Microsoft.Win32.RegistryKey config;
249 config = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("System").OpenSubKey("CurrentControlSet").OpenSubKey("Services").OpenSubKey(MyServiceName, true);
250 if (args.Length > 1)
251 {
252 config.SetValue("ImagePath", config.GetValue("ImagePath") + " -s " + string.Join(" ", args, argNo, args.Length - argNo - 1));
253 }
254 else
255 {
256 config.SetValue("ImagePath", config.GetValue("ImagePath") + " -s");
257 }
259 Console.WriteLine("Service installed successfully.");
260 }
261 catch (Win32Exception exWin32Exception)
262 {
263 if (exWin32Exception.NativeErrorCode == 1073)
264 {
265 Console.WriteLine("Service already exists.");
266 return;
267 }
268 else
269 throw exWin32Exception;
270 }
271 return;
272 }
273 case "-u":
274 {
275 IDictionary mySavedState = new Hashtable();
276 Installer i = MakeServiceInstaller();
278 try
279 {
280 i.Uninstall(null);
281 Console.WriteLine("Service uninstalled successfully.");
282 }
283 catch (InstallException exInstallException)
284 {
285 if (exInstallException.InnerException is Win32Exception)
286 {
287 Win32Exception exWin32Exception = (Win32Exception)exInstallException.InnerException;
288 if (exWin32Exception.NativeErrorCode == 1060)
289 {
290 Console.WriteLine("Service does not exist.");
291 return;
292 }
293 }
294 throw exInstallException;
295 }
296 return;
297 }
298 case "-s": // run as service
299 ServiceBase.Run(new Program());
300 return;
301 }
302 }
303 Console.WriteLine("Connecting to kernel driver...");
304 new Program().Run();
305 }
307 public Program()
308 {
309 this.ServiceName = MyServiceName;
310 this.CanHandlePowerEvent = false;
311 this.CanHandleSessionChangeEvent = false;
312 this.CanPauseAndContinue = false;
313 this.CanShutdown = false;
314 this.CanStop = true;
315 }
317 private Thread workerThread = null;
319 protected override void OnStart(string[] args)
320 {
321 workerThread = new Thread(new ThreadStart(Run));
322 workerThread.Start();
323 }
325 protected override void OnStop()
326 {
327 workerThread.Abort();
328 workerThread.Join();
329 }
331 protected void Run()
332 {
333 SafeFileHandle handle;
334 byte[] buf = new byte[128];
336 handle = CreateFile(GetXenInterfacePath(), FILE_GENERIC_READ, 0, IntPtr.Zero, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, IntPtr.Zero);
337 FileStream fs = new FileStream(handle, FileAccess.Read);
338 StreamReader sr = new StreamReader(fs);
339 Console.WriteLine("Opened");
340 while (true)
341 {
342 string command = sr.ReadLine();
344 Console.WriteLine("Command = " + command);
346 switch (command)
347 {
348 case "":
349 break;
350 case "reboot":
351 //DoExitWin(EWX_REBOOT | EWX_FORCE);
352 //DoExitWin(ExitWindows.Reboot | ExitWindows.ForceIfHung);
353 DoExitWin(true, true);
354 break;
355 case "poweroff":
356 case "halt":
357 default:
358 //DoExitWin(EWX_POWEROFF | EWX_FORCE);
359 //DoExitWin(ExitWindows.PowerOff | ExitWindows.ForceIfHung);
360 DoExitWin(true, false);
361 break;
362 }
363 }
364 }
365 }
366 }