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

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

Move Get/SetFileTimes? together with the FileTimeToDateTime/DateTimeToFileTime? functions

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