source: branches/eraser6/CodeReview/Eraser.Util/KernelApi.cs @ 1543

Revision 1543, 15.5 KB checked in by lowjoel, 5 years ago (diff)

Moved all the NativeMethods? declarations to the NativeMethods? folder with filenames equal to the DLL the functions import from. Addresses #284: Eraser.Util rewrite

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1/*
2 * $Id$
3 * Copyright 2008-2009 The Eraser Project
4 * Original Author: Joel Low <lowjoel@users.sourceforge.net>
5 * Modified By: Garrett Trant <gtrant@users.sourceforge.net>
6 *
7 * This file is part of Eraser.
8 *
9 * Eraser is free software: you can redistribute it and/or modify it under the
10 * terms of the GNU General Public License as published by the Free Software
11 * Foundation, either version 3 of the License, or (at your option) any later
12 * version.
13 *
14 * Eraser is distributed in the hope that it will be useful, but WITHOUT ANY
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17 *
18 * A copy of the GNU General Public License can be found at
19 * <http://www.gnu.org/licenses/>.
20 */
21
22using System;
23using System.Collections.Generic;
24using System.Text;
25using System.Reflection;
26using System.Runtime.InteropServices;
27using Microsoft.Win32.SafeHandles;
28using System.ComponentModel;
29
30namespace Eraser.Util
31{
32    public static class KernelApi
33    {
34        /// <summary>
35        /// Allocates a new console for the calling process.
36        /// </summary>
37        /// <returns>If the function succeeds, the return value is nonzero.
38        ///
39        /// If the function fails, the return value is zero. To get extended error
40        /// information, call Marshal.GetLastWin32Error.</returns>
41        /// <remarks>A process can be associated with only one console, so the AllocConsole
42        /// function fails if the calling process already has a console. A process can
43        /// use the FreeConsole function to detach itself from its current console, then
44        /// it can call AllocConsole to create a new console or AttachConsole to attach
45        /// to another console.
46        ///
47        /// If the calling process creates a child process, the child inherits the
48        /// new console.
49        ///
50        /// AllocConsole initializes standard input, standard output, and standard error
51        /// handles for the new console. The standard input handle is a handle to the
52        /// console's input buffer, and the standard output and standard error handles
53        /// are handles to the console's screen buffer. To retrieve these handles, use
54        /// the GetStdHandle function.
55        ///
56        /// This function is primarily used by graphical user interface (GUI) application
57        /// to create a console window. GUI applications are initialized without a
58        /// console. Console applications are initialized with a console, unless they
59        /// are created as detached processes (by calling the CreateProcess function
60        /// with the DETACHED_PROCESS flag).</remarks>
61        public static bool AllocConsole()
62        {
63            return NativeMethods.AllocConsole();
64        }
65
66        /// <summary>
67        /// Detaches the calling process from its console.
68        /// </summary>
69        /// <returns>If the function succeeds, the return value is nonzero.
70        ///
71        /// If the function fails, the return value is zero. To get extended error
72        /// information, call Marshal.GetLastWin32Error.</returns>
73        /// <remarks>A process can be attached to at most one console. If the calling
74        /// process is not already attached to a console, the error code returned is
75        /// ERROR_INVALID_PARAMETER (87).
76        ///
77        /// A process can use the FreeConsole function to detach itself from its
78        /// console. If other processes share the console, the console is not destroyed,
79        /// but the process that called FreeConsole cannot refer to it. A console is
80        /// closed when the last process attached to it terminates or calls FreeConsole.
81        /// After a process calls FreeConsole, it can call the AllocConsole function to
82        /// create a new console or AttachConsole to attach to another console.</remarks>
83        public static bool FreeConsole()
84        {
85            return NativeMethods.FreeConsole();
86        }
87
88        private static DateTime FileTimeToDateTime(System.Runtime.InteropServices.ComTypes.FILETIME value)
89        {
90            long time = (long)((((ulong)value.dwHighDateTime) << sizeof(int) * 8) |
91                (uint)value.dwLowDateTime);
92            return DateTime.FromFileTime(time);
93        }
94
95        private static System.Runtime.InteropServices.ComTypes.FILETIME DateTimeToFileTime(DateTime value)
96        {
97            long time = value.ToFileTime();
98
99            System.Runtime.InteropServices.ComTypes.FILETIME result =
100                new System.Runtime.InteropServices.ComTypes.FILETIME();
101            result.dwLowDateTime = (int)(time & 0xFFFFFFFFL);
102            result.dwHighDateTime = (int)(time >> 32);
103
104            return result;
105        }
106
107        /// <summary>
108        /// Converts a Win32 Error code to a HRESULT.
109        /// </summary>
110        /// <param name="errorCode">The error code to convert.</param>
111        /// <returns>A HRESULT value representing the error code.</returns>
112        internal static int GetHRForWin32Error(int errorCode)
113        {
114            const uint FACILITY_WIN32 = 7;
115            return errorCode <= 0 ? errorCode :
116                (int)((((uint)errorCode) & 0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000);
117        }
118
119        /// <summary>
120        /// Gets a Exception for the given Win32 error code.
121        /// </summary>
122        /// <param name="errorCode">The error code.</param>
123        /// <returns>An exception object representing the error code.</returns>
124        internal static Exception GetExceptionForWin32Error(int errorCode)
125        {
126            int HR = GetHRForWin32Error(errorCode);
127            return Marshal.GetExceptionForHR(HR);
128        }
129
130        public static void GetFileTime(SafeFileHandle file, out DateTime creationTime,
131            out DateTime accessedTime, out DateTime modifiedTime)
132        {
133            System.Runtime.InteropServices.ComTypes.FILETIME accessedTimeNative =
134                new System.Runtime.InteropServices.ComTypes.FILETIME();
135            System.Runtime.InteropServices.ComTypes.FILETIME modifiedTimeNative =
136                new System.Runtime.InteropServices.ComTypes.FILETIME();
137            System.Runtime.InteropServices.ComTypes.FILETIME createdTimeNative =
138                new System.Runtime.InteropServices.ComTypes.FILETIME();
139
140            if (!NativeMethods.GetFileTime(file, out createdTimeNative, out accessedTimeNative,
141                out modifiedTimeNative))
142            {
143                throw GetExceptionForWin32Error(Marshal.GetLastWin32Error());
144            }
145
146            creationTime = FileTimeToDateTime(createdTimeNative);
147            accessedTime = FileTimeToDateTime(accessedTimeNative);
148            modifiedTime = FileTimeToDateTime(modifiedTimeNative);
149        }
150
151        public static void SetFileTime(SafeFileHandle file, DateTime creationTime,
152            DateTime accessedTime, DateTime modifiedTime)
153        {
154            System.Runtime.InteropServices.ComTypes.FILETIME accessedTimeNative =
155                new System.Runtime.InteropServices.ComTypes.FILETIME();
156            System.Runtime.InteropServices.ComTypes.FILETIME modifiedTimeNative =
157                new System.Runtime.InteropServices.ComTypes.FILETIME();
158            System.Runtime.InteropServices.ComTypes.FILETIME createdTimeNative =
159                new System.Runtime.InteropServices.ComTypes.FILETIME();
160
161            if (!NativeMethods.GetFileTime(file, out createdTimeNative,
162                out accessedTimeNative, out modifiedTimeNative))
163            {
164                throw KernelApi.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
165            }
166
167            if (creationTime != DateTime.MinValue)
168                createdTimeNative = DateTimeToFileTime(creationTime);
169            if (accessedTime != DateTime.MinValue)
170                accessedTimeNative = DateTimeToFileTime(accessedTime);
171            if (modifiedTime != DateTime.MinValue)
172                modifiedTimeNative = DateTimeToFileTime(modifiedTime);
173
174            if (!NativeMethods.SetFileTime(file, ref createdTimeNative,
175                ref accessedTimeNative, ref modifiedTimeNative))
176            {
177                throw KernelApi.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
178            }
179        }
180
181        /// <summary>
182        /// Retrieves the current value of the high-resolution performance counter.
183        /// </summary>
184        public static long PerformanceCounter
185        {
186            get
187            {
188                long result = 0;
189                if (NativeMethods.QueryPerformanceCounter(out result))
190                    return result;
191                return 0;
192            }
193        }
194
195        /// <summary>
196        /// Gets the current CPU type of the system.
197        /// </summary>
198        /// <returns>One of the <see cref="ProcessorTypes"/> enumeration values.</returns>
199        public static ProcessorArchitecture ProcessorArchitecture
200        {
201            get
202            {
203                NativeMethods.SYSTEM_INFO info = new NativeMethods.SYSTEM_INFO();
204                NativeMethods.GetSystemInfo(out info);
205
206                switch (info.processorArchitecture)
207                {
208                    case NativeMethods.SYSTEM_INFO.ProcessorArchitecture.PROCESSOR_ARCHITECTURE_AMD64:
209                        return ProcessorArchitecture.Amd64;
210                    case NativeMethods.SYSTEM_INFO.ProcessorArchitecture.PROCESSOR_ARCHITECTURE_IA64:
211                        return ProcessorArchitecture.IA64;
212                    case NativeMethods.SYSTEM_INFO.ProcessorArchitecture.PROCESSOR_ARCHITECTURE_INTEL:
213                        return ProcessorArchitecture.X86;
214                    default:
215                        return ProcessorArchitecture.None;
216                }
217            }
218        }
219
220        /// <summary>
221        /// Enables an application to inform the system that it is in use, thereby
222        /// preventing the system from entering sleep or turning off the display
223        /// while the application is running.
224        /// </summary>
225        /// <param name="executionState">The thread's execution requirements. This
226        /// parameter can be one or more of the EXECUTION_STATE values.</param>
227        /// <returns>If the function succeeds, the return value is the previous
228        /// thread execution state.
229        ///
230        /// If the function fails, the return value is NULL.</returns>
231        /// <remarks>The system automatically detects activities such as local keyboard
232        /// or mouse input, server activity, and changing window focus. Activities
233        /// that are not automatically detected include disk or CPU activity and
234        /// video display.
235        ///
236        /// Calling SetThreadExecutionState without ES_CONTINUOUS simply resets
237        /// the idle timer; to keep the display or system in the working state,
238        /// the thread must call SetThreadExecutionState periodically.
239        ///
240        /// To run properly on a power-managed computer, applications such as fax
241        /// servers, answering machines, backup agents, and network management
242        /// applications must use both ES_SYSTEM_REQUIRED and ES_CONTINUOUS when
243        /// they process events. Multimedia applications, such as video players
244        /// and presentation applications, must use ES_DISPLAY_REQUIRED when they
245        /// display video for long periods of time without user input. Applications
246        /// such as word processors, spreadsheets, browsers, and games do not need
247        /// to call SetThreadExecutionState.
248        ///
249        /// The ES_AWAYMODE_REQUIRED value should be used only when absolutely
250        /// necessary by media applications that require the system to perform
251        /// background tasks such as recording television content or streaming media
252        /// to other devices while the system appears to be sleeping. Applications
253        /// that do not require critical background processing or that run on
254        /// portable computers should not enable away mode because it prevents
255        /// the system from conserving power by entering true sleep.
256        ///
257        /// To enable away mode, an application uses both ES_AWAYMODE_REQUIRED and
258        /// ES_CONTINUOUS; to disable away mode, an application calls
259        /// SetThreadExecutionState with ES_CONTINUOUS and clears
260        /// ES_AWAYMODE_REQUIRED. When away mode is enabled, any operation that
261        /// would put the computer to sleep puts it in away mode instead. The computer
262        /// appears to be sleeping while the system continues to perform tasks that
263        /// do not require user input. Away mode does not affect the sleep idle
264        /// timer; to prevent the system from entering sleep when the timer expires,
265        /// an application must also set the ES_SYSTEM_REQUIRED value.
266        ///
267        /// The SetThreadExecutionState function cannot be used to prevent the user
268        /// from putting the computer to sleep. Applications should respect that
269        /// the user expects a certain behavior when they close the lid on their
270        /// laptop or press the power button.
271        ///
272        /// This function does not stop the screen saver from executing.
273        /// </remarks>
274        public static ThreadExecutionState SetThreadExecutionState(
275            ThreadExecutionState executionState)
276        {
277            return (ThreadExecutionState)NativeMethods.SetThreadExecutionState(
278                (NativeMethods.EXECUTION_STATE)executionState);
279        }
280
281        public class DiskPerformanceInfo
282        {
283            unsafe internal DiskPerformanceInfo(NativeMethods.DiskPerformanceInfoInternal info)
284            {
285                BytesRead = info.BytesRead;
286                BytesWritten = info.BytesWritten;
287                ReadTime = info.ReadTime;
288                WriteTime = info.WriteTime;
289                IdleTime = info.IdleTime;
290                ReadCount = info.ReadCount;
291                WriteCount = info.WriteCount;
292                QueueDepth = info.QueueDepth;
293                SplitCount = info.SplitCount;
294                QueryTime = info.QueryTime;
295                StorageDeviceNumber = info.StorageDeviceNumber;
296                StorageManagerName = new string((char*)info.StorageManagerName);
297            }
298
299            public long BytesRead { get; private set; }
300            public long BytesWritten { get; private set; }
301            public long ReadTime { get; private set; }
302            public long WriteTime { get; private set; }
303            public long IdleTime { get; private set; }
304            public uint ReadCount { get; private set; }
305            public uint WriteCount { get; private set; }
306            public uint QueueDepth { get; private set; }
307            public uint SplitCount { get; private set; }
308            public long QueryTime { get; private set; }
309            public uint StorageDeviceNumber { get; private set; }
310            public string StorageManagerName { get; private set; }
311        }
312
313        /// <summary>
314        /// Queries the performance information for the given disk.
315        /// </summary>
316        /// <param name="diskHandle">A read-only handle to a device (disk).</param>
317        /// <returns>A DiskPerformanceInfo structure describing the performance
318        /// information for the given disk.</returns>
319        public static DiskPerformanceInfo QueryDiskPerformanceInfo(SafeFileHandle diskHandle)
320        {
321            if (diskHandle.IsInvalid)
322                throw new ArgumentException("The disk handle must not be invalid.");
323
324            //This only works if the user has turned on the disk performance
325            //counters with 'diskperf -y'. These counters are off by default
326            NativeMethods.DiskPerformanceInfoInternal result =
327                new NativeMethods.DiskPerformanceInfoInternal();
328            uint bytesReturned = 0;
329            if (NativeMethods.DeviceIoControl(diskHandle, NativeMethods.IOCTL_DISK_PERFORMANCE,
330                IntPtr.Zero, 0, out result, (uint)Marshal.SizeOf(result), out bytesReturned, IntPtr.Zero))
331            {
332                return new DiskPerformanceInfo(result);
333            }
334
335            return null;
336        }
337    }
338
339    public enum ThreadExecutionState
340    {
341        /// <summary>
342        /// No specific state
343        /// </summary>
344        None = 0,
345
346        /// <summary>
347        /// Enables away mode. This value must be specified with ES_CONTINUOUS.
348        ///
349        /// Away mode should be used only by media-recording and media-distribution
350        /// applications that must perform critical background processing on
351        /// desktop computers while the computer appears to be sleeping.
352        /// See remarks.
353        ///
354        /// Windows Server 2003 and Windows XP/2000: ES_AWAYMODE_REQUIRED is
355        /// not supported.
356        /// </summary>
357        AwayModeRequired = (int)NativeMethods.EXECUTION_STATE.ES_AWAYMODE_REQUIRED,
358
359        /// <summary>
360        /// Informs the system that the state being set should remain in effect
361        /// until the next call that uses ES_CONTINUOUS and one of the other
362        /// state flags is cleared.
363        /// </summary>
364        Continuous = unchecked((int)NativeMethods.EXECUTION_STATE.ES_CONTINUOUS),
365
366        /// <summary>
367        /// Forces the display to be on by resetting the display idle timer.
368        /// </summary>
369        DisplayRequired = (int)NativeMethods.EXECUTION_STATE.ES_DISPLAY_REQUIRED,
370
371        /// <summary>
372        /// Forces the system to be in the working state by resetting the system
373        /// idle timer.
374        /// </summary>
375        SystemRequired = (int)NativeMethods.EXECUTION_STATE.ES_SYSTEM_REQUIRED,
376
377        /// <summary>
378        /// This value is not supported. If ES_USER_PRESENT is combined with
379        /// other esFlags values, the call will fail and none of the specified
380        /// states will be set.
381        ///
382        /// Windows Server 2003 and Windows XP/2000: Informs the system that a
383        /// user is present and resets the display and system idle timers.
384        /// ES_USER_PRESENT must be called with ES_CONTINUOUS.
385        /// </summary>
386        UserPresent = (int)NativeMethods.EXECUTION_STATE.ES_USER_PRESENT
387    }
388}
Note: See TracBrowser for help on using the repository browser.