source: trunk/eraser/Eraser.Util/NativeMethods/Kernel.cs @ 2208

Revision 2208, 61.4 KB checked in by lowjoel, 4 years ago (diff)

Call the extension methods class Methods instead of breaking up to separate classes, to reduce name conflicts.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1/*
2 * $Id$
3 * Copyright 2008-2010 The Eraser Project
4 * Original Author: Joel Low <lowjoel@users.sourceforge.net>
5 * Modified By:
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.Runtime.InteropServices;
26using Microsoft.Win32.SafeHandles;
27
28namespace Eraser.Util
29{
30    /// <summary>
31    /// Stores Kernel32.dll functions, structs and constants.
32    /// </summary>
33    internal static partial class NativeMethods
34    {
35        /// <summary>
36        /// Copies an existing file to a new file, notifying the application of
37        /// its progress through a callback function.
38        /// </summary>
39        /// <param name="lpExistingFileName">The name of an existing file.
40        ///
41        /// In the ANSI version of this function, the name is limited to MAX_PATH
42        /// characters. To extend this limit to 32,767 wide characters, call the
43        /// ]Unicode version of the function and prepend "\\?\" to the path.
44        /// For more information, see Naming a File.
45        ///
46        /// If lpExistingFileName does not exist, the CopyFileEx function fails,
47        /// and the GetLastError function returns ERROR_FILE_NOT_FOUND.</param>
48        /// <param name="lpNewFileName">The name of the new file.
49        ///
50        /// In the ANSI version of this function, the name is limited to MAX_PATH
51        /// characters. To extend this limit to 32,767 wide characters, call the
52        /// Unicode version of the function and prepend "\\?\" to the path. For
53        /// more information, see Naming a File.</param>
54        /// <param name="lpProgressRoutine">The address of a callback function of
55        /// type <see cref="ExtensionMethods.IO.CopyProgressFunction"/> that is
56        /// called each time another portion of the file has been copied. This
57        /// parameter can be NULL. For more information on the progress callback
58        /// function, see the <see cref="ExtensionMethods.IO.CopyProgressFunction"/>
59        /// function.</param>
60        /// <param name="lpData">The argument to be passed to the callback function.
61        /// This parameter can be NULL.</param>
62        /// <param name="pbCancel">If this flag is set to TRUE during the copy
63        /// operation, the operation is canceled. Otherwise, the copy operation
64        /// will continue to completion.</param>
65        /// <param name="dwCopyFlags">Flags that specify how the file is to be
66        /// copied. This parameter can be a combination of the
67        /// <see cref="CopyFileFlags"/> enumeration.
68        /// </param>
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 information
72        /// call <see cref="Marshal.GetLastWin32Error"/>.
73        ///
74        /// If lpProgressRoutine returns PROGRESS_CANCEL due to the user canceling the
75        /// operation, CopyFileEx will return zero and GetLastError will return
76        /// ERROR_REQUEST_ABORTED. In this case, the partially copied destination file is
77        /// deleted.
78        ///
79        /// If lpProgressRoutine returns PROGRESS_STOP due to the user stopping the
80        /// operation, CopyFileEx will return zero and GetLastError will return
81        /// ERROR_REQUEST_ABORTED. In this case, the partially copied destination file
82        /// is left intact.</returns>
83        [DllImport("Kernel32.dll", SetLastError = true)]
84        public static extern bool CopyFileEx(string lpExistingFileName,
85            string lpNewFileName, CopyProgressFunction lpProgressRoutine,
86            IntPtr lpData, ref bool pbCancel, CopyFileFlags dwCopyFlags);
87
88        /// <summary>
89        /// Flags used with <see cref="CopyFileEx"/>
90        /// </summary>
91        [Flags]
92        public enum CopyFileFlags
93        {
94            /// <summary>
95            /// An attempt to copy an encrypted file will succeed even if the
96            /// destination copy cannot be encrypted.
97            ///
98            /// Windows 2000: This value is not supported.
99            /// </summary>
100            AllowDecryptedDestination = 0x00000008,
101
102            /// <summary>
103            /// If the source file is a symbolic link, the destination file is
104            /// also a symbolic link pointing to the same file that the source
105            /// symbolic link is pointing to.
106            ///
107            /// Windows Server 2003 and Windows XP/2000: This value is not
108            /// supported.
109            /// </summary>
110            CopySymlink = 0x00000800,
111
112            /// <summary>
113            /// The copy operation fails immediately if the target file already
114            /// exists.
115            /// </summary>
116            FailIfExists = 0x00000001,
117
118            /// <summary>
119            /// The copy operation is performed using unbuffered I/O, bypassing
120            /// system I/O cache resources. Recommended for very large file
121            /// transfers.
122            ///
123            /// Windows Server 2003 and Windows XP/2000: This value is not
124            /// supported.
125            /// </summary>
126            NoBuffering = 0x00001000,
127
128            /// <summary>
129            /// The file is copied and the original file is opened for write
130            /// access.
131            /// </summary>
132            OpenSourceForWrite = 0x00000004,
133
134            /// <summary>
135            /// Progress of the copy is tracked in the target file in case the
136            /// copy fails. The failed copy can be restarted at a later time by
137            /// specifying the same values for lpExistingFileName and lpNewFileName
138            /// as those used in the call that failed.
139            /// </summary>
140            Restartable = 0x00000002
141        }
142
143        /// <summary>
144        /// An application-defined callback function used with the CopyFileEx,
145        /// MoveFileTransacted, and MoveFileWithProgress functions. It is called when
146        /// a portion of a copy or move operation is completed. The LPPROGRESS_ROUTINE
147        /// type defines a pointer to this callback function. CopyProgressRoutine is
148        /// a placeholder for the application-defined function name.
149        /// </summary>
150        /// <param name="TotalFileSize">The total size of the file, in bytes.</param>
151        /// <param name="TotalBytesTransferred">The total number of bytes
152        /// transferred from the source file to the destination file since the
153        /// copy operation began.</param>
154        /// <param name="StreamSize">The total size of the current file stream,
155        /// in bytes.</param>
156        /// <param name="StreamBytesTransferred">The total number of bytes in the
157        /// current stream that have been transferred from the source file to the
158        /// destination file since the copy operation began.</param>
159        /// <param name="dwStreamNumber">A handle to the current stream. The
160        /// first time CopyProgressRoutine is called, the stream number is 1.</param>
161        /// <param name="dwCallbackReason">The reason that CopyProgressRoutine was
162        /// called. This parameter can be one of the following values.</param>
163        /// <param name="hSourceFile">A handle to the source file.</param>
164        /// <param name="hDestinationFile">A handle to the destination file.</param>
165        /// <param name="lpData">Argument passed to CopyProgressRoutine by CopyFileEx,
166        /// MoveFileTransacted, or MoveFileWithProgress.</param>
167        /// <returns>The CopyProgressRoutine function should return one of the
168        /// <see cref="CopyProgressFunctionResult"/> values.</returns>
169        public delegate ExtensionMethods.Methods.CopyProgressFunctionResult
170            CopyProgressFunction(long TotalFileSize, long TotalBytesTransferred,
171            long StreamSize, long StreamBytesTransferred, uint dwStreamNumber,
172            CopyProgressFunctionCallbackReasons dwCallbackReason,
173            IntPtr hSourceFile, IntPtr hDestinationFile, IntPtr lpData);
174
175        /// <summary>
176        /// Callback reasons for the <see cref="CopyProgressFunction"/> callbacks.
177        /// </summary>
178        public enum CopyProgressFunctionCallbackReasons
179        {
180            /// <summary>
181            /// Another part of the data file was copied.
182            /// </summary>
183            ChunkFinished = 0x00000000,
184
185            /// <summary>
186            /// Another stream was created and is about to be copied. This is
187            /// the callback reason given when the callback routine is first invoked.
188            /// </summary>
189            StreamSwitch = 0x00000001
190        }
191
192        /// <summary>
193        /// Deletes an existing file.
194        /// </summary>
195        /// <param name="lpFileName">The name of the file to be deleted.
196        ///
197        /// In the ANSI version of this function, the name is limited to MAX_PATH
198        /// characters. To extend this limit to 32,767 wide characters, call
199        /// the Unicode version of the function and prepend "\\?\" to the path.
200        /// For more information, see Naming a File.</param>
201        /// <returns>If the function succeeds, the return value is nonzero.
202        ///
203        /// If the function fails, the return value is zero (0). To get extended
204        /// error information, call Marshal.GetLastWin32Error().</returns>
205        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
206        [return: MarshalAs(UnmanagedType.Bool)]
207        public static extern bool DeleteFile(string lpFileName);
208
209        /// <summary>
210        /// Retrieves information about the current system.
211        /// </summary>
212        /// <param name="lpSystemInfo">A pointer to a SYSTEM_INFO structure that
213        /// receives the information.</param>
214        [DllImport("Kernel32.dll")]
215        public static extern void GetSystemInfo(out SYSTEM_INFO lpSystemInfo);
216
217        /// <summary>
218        /// The QueryPerformanceCounter function retrieves the current value of
219        /// the high-resolution performance counter.
220        /// </summary>
221        /// <param name="lpPerformanceCount">[out] Pointer to a variable that receives
222        /// the current performance-counter value, in counts.</param>
223        /// <returns>If the function succeeds, the return value is nonzero.
224        ///
225        /// If the function fails, the return value is zero. To get extended error
226        /// information, call Marshal.GetLastWin32Error. </returns>
227        [DllImport("Kernel32.dll", SetLastError = true)]
228        [return: MarshalAs(UnmanagedType.Bool)]
229        public static extern bool QueryPerformanceCounter(out long lpPerformanceCount);
230
231        /// <summary>
232        /// Contains information about the current computer system. This includes
233        /// the architecture and type of the processor, the number of processors
234        /// in the system, the page size, and other such information.
235        /// </summary>
236        [StructLayout(LayoutKind.Sequential)]
237        internal struct SYSTEM_INFO
238        {
239            /// <summary>
240            /// Represents a list of processor architectures.
241            /// </summary>
242            public enum ProcessorArchitecture : ushort
243            {
244                /// <summary>
245                /// x64 (AMD or Intel).
246                /// </summary>
247                PROCESSOR_ARCHITECTURE_AMD64 = 9,
248
249                /// <summary>
250                /// Intel Itanium Processor Family (IPF).
251                /// </summary>
252                PROCESSOR_ARCHITECTURE_IA64 = 6,
253
254                /// <summary>
255                /// x86.
256                /// </summary>
257                PROCESSOR_ARCHITECTURE_INTEL = 0,
258
259                /// <summary>
260                /// Unknown architecture.
261                /// </summary>
262                PROCESSOR_ARCHITECTURE_UNKNOWN = 0xffff
263            }
264
265            /// <summary>
266            /// The processor architecture of the installed operating system.
267            /// This member can be one of the ProcessorArchitecture values.
268            /// </summary>
269            public ProcessorArchitecture processorArchitecture;
270
271            /// <summary>
272            /// This member is reserved for future use.
273            /// </summary>
274            private const ushort reserved = 0;
275
276            /// <summary>
277            /// The page size and the granularity of page protection and commitment.
278            /// This is the page size used by the VirtualAlloc function.
279            /// </summary>
280            public uint pageSize;
281
282            /// <summary>
283            /// A pointer to the lowest memory address accessible to applications
284            /// and dynamic-link libraries (DLLs).
285            /// </summary>
286            public IntPtr minimumApplicationAddress;
287
288            /// <summary>
289            /// A pointer to the highest memory address accessible to applications
290            /// and DLLs.
291            /// </summary>
292            public IntPtr maximumApplicationAddress;
293
294            /// <summary>
295            /// A mask representing the set of processors configured into the system.
296            /// Bit 0 is processor 0; bit 31 is processor 31.
297            /// </summary>
298            public IntPtr activeProcessorMask;
299
300            /// <summary>
301            /// The number of processors in the system.
302            /// </summary>
303            public uint numberOfProcessors;
304
305            /// <summary>
306            /// An obsolete member that is retained for compatibility. Use the
307            /// wProcessorArchitecture, wProcessorLevel, and wProcessorRevision
308            /// members to determine the type of processor.
309            /// Name                        Value
310            /// PROCESSOR_INTEL_386         386
311            /// PROCESSOR_INTEL_486         486
312            /// PROCESSOR_INTEL_PENTIUM     586
313            /// PROCESSOR_INTEL_IA64        2200
314            /// PROCESSOR_AMD_X8664         8664
315            /// </summary>
316            public uint processorType;
317
318            /// <summary>
319            /// The granularity for the starting address at which virtual memory
320            /// can be allocated. For more information, see VirtualAlloc.
321            /// </summary>
322            public uint allocationGranularity;
323
324            /// <summary>
325            /// The architecture-dependent processor level. It should be used only
326            /// for display purposes. To determine the feature set of a processor,
327            /// use the IsProcessorFeaturePresent function.
328            ///
329            /// If wProcessorArchitecture is PROCESSOR_ARCHITECTURE_INTEL, wProcessorLevel
330            /// is defined by the CPU vendor.
331            /// If wProcessorArchitecture is PROCESSOR_ARCHITECTURE_IA64, wProcessorLevel
332            /// is set to 1.
333            /// </summary>
334            public ushort processorLevel;
335
336            /// <summary>
337            /// The architecture-dependent processor revision. The following table
338            /// shows how the revision value is assembled for each type of
339            /// processor architecture.
340            ///
341            /// Processor                   Value
342            /// Intel Pentium, Cyrix        The high byte is the model and the
343            /// or NextGen 586              low byte is the stepping. For example,
344            ///                             if the value is xxyy, the model number
345            ///                             and stepping can be displayed as follows:
346            ///                             Model xx, Stepping yy
347            /// Intel 80386 or 80486        A value of the form xxyz.
348            ///                             If xx is equal to 0xFF, y - 0xA is the model
349            ///                             number, and z is the stepping identifier.
350            ///
351            ///                             If xx is not equal to 0xFF, xx + 'A'
352            ///                             is the stepping letter and yz is the minor stepping.
353            /// </summary>
354            public ushort processorRevision;
355        }
356
357        [DllImport("Kernel32.dll")]
358        public static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
359
360        [Flags]
361        public enum EXECUTION_STATE : uint
362        {
363            ES_AWAYMODE_REQUIRED = 0x00000040,
364            ES_CONTINUOUS = 0x80000000,
365            ES_DISPLAY_REQUIRED = 0x00000002,
366            ES_SYSTEM_REQUIRED = 0x00000001,
367            ES_USER_PRESENT = 0x00000004
368        }
369
370        /// <summary>
371        /// Allocates a new console for the calling process.
372        /// </summary>
373        /// <returns>If the function succeeds, the return value is nonzero.
374        ///
375        /// If the function fails, the return value is zero. To get extended error
376        /// information, call Marshal.GetLastWin32Error.</returns>
377        /// <remarks>A process can be associated with only one console, so the AllocConsole
378        /// function fails if the calling process already has a console. A process can
379        /// use the FreeConsole function to detach itself from its current console, then
380        /// it can call AllocConsole to create a new console or AttachConsole to attach
381        /// to another console.
382        ///
383        /// If the calling process creates a child process, the child inherits the
384        /// new console.
385        ///
386        /// AllocConsole initializes standard input, standard output, and standard error
387        /// handles for the new console. The standard input handle is a handle to the
388        /// console's input buffer, and the standard output and standard error handles
389        /// are handles to the console's screen buffer. To retrieve these handles, use
390        /// the GetStdHandle function.
391        ///
392        /// This function is primarily used by graphical user interface (GUI) application
393        /// to create a console window. GUI applications are initialized without a
394        /// console. Console applications are initialized with a console, unless they
395        /// are created as detached processes (by calling the CreateProcess function
396        /// with the DETACHED_PROCESS flag).</remarks>
397        [DllImport("Kernel32.dll", SetLastError = true)]
398        [return: MarshalAs(UnmanagedType.Bool)]
399        public static extern bool AllocConsole();
400
401        /// <summary>
402        /// Detaches the calling process from its console.
403        /// </summary>
404        /// <returns>If the function succeeds, the return value is nonzero.
405        ///
406        /// If the function fails, the return value is zero. To get extended error
407        /// information, call Marshal.GetLastWin32Error.</returns>
408        /// <remarks>A process can be attached to at most one console. If the calling
409        /// process is not already attached to a console, the error code returned is
410        /// ERROR_INVALID_PARAMETER (87).
411        ///
412        /// A process can use the FreeConsole function to detach itself from its
413        /// console. If other processes share the console, the console is not destroyed,
414        /// but the process that called FreeConsole cannot refer to it. A console is
415        /// closed when the last process attached to it terminates or calls FreeConsole.
416        /// After a process calls FreeConsole, it can call the AllocConsole function to
417        /// create a new console or AttachConsole to attach to another console.</remarks>
418        [DllImport("Kernel32.dll", SetLastError = true)]
419        [return: MarshalAs(UnmanagedType.Bool)]
420        public static extern bool FreeConsole();
421
422        /// <summary>
423        /// The CreateFile function creates or opens a file, file stream, directory,
424        /// physical disk, volume, console buffer, tape drive, communications resource,
425        /// mailslot, or named pipe. The function returns a handle that can be used
426        /// to access an object.
427        /// </summary>
428        /// <param name="FileName"></param>
429        /// <param name="DesiredAccess"> access to the object, which can be read,
430        /// write, or both</param>
431        /// <param name="ShareMode">The sharing mode of an object, which can be
432        /// read, write, both, or none</param>
433        /// <param name="SecurityAttributes">A pointer to a SECURITY_ATTRIBUTES
434        /// structure that determines whether or not the returned handle can be
435        /// inherited by child processes. Can be null</param>
436        /// <param name="CreationDisposition">An action to take on files that exist
437        /// and do not exist</param>
438        /// <param name="FlagsAndAttributes">The file attributes and flags.</param>
439        /// <param name="hTemplateFile">A handle to a template file with the
440        /// GENERIC_READ access right. The template file supplies file attributes
441        /// and extended attributes for the file that is being created. This
442        /// parameter can be null</param>
443        /// <returns>If the function succeeds, the return value is an open handle
444        /// to a specified file. If a specified file exists before the function
445        /// all and dwCreationDisposition is CREATE_ALWAYS or OPEN_ALWAYS, a call
446        /// to GetLastError returns ERROR_ALREADY_EXISTS, even when the function
447        /// succeeds. If a file does not exist before the call, GetLastError
448        /// returns 0.
449        ///
450        /// If the function fails, the return value is INVALID_HANDLE_VALUE.
451        /// To get extended error information, call Marshal.GetLastWin32Error().</returns>
452        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
453        public static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess,
454            uint dwShareMode, IntPtr SecurityAttributes, uint dwCreationDisposition,
455            uint dwFlagsAndAttributes, IntPtr hTemplateFile);
456
457        public const uint FILE_READ_ATTRIBUTES = 0x0080;
458        public const uint FILE_WRITE_ATTRIBUTES = 0x0100;
459        public const uint GENERIC_READ = 0x80000000;
460        public const uint GENERIC_WRITE = 0x40000000;
461        public const uint GENERIC_EXECUTE = 0x20000000;
462        public const uint GENERIC_ALL = 0x10000000;
463
464        public const uint FILE_SHARE_READ = 0x00000001;
465        public const uint FILE_SHARE_WRITE = 0x00000002;
466        public const uint FILE_SHARE_DELETE = 0x00000004;
467
468        public const uint CREATE_NEW = 1;
469        public const uint CREATE_ALWAYS = 2;
470        public const uint OPEN_EXISTING = 3;
471        public const uint OPEN_ALWAYS = 4;
472        public const uint TRUNCATE_EXISTING = 5;
473
474        public const uint FILE_FLAG_WRITE_THROUGH = 0x80000000;
475        public const uint FILE_FLAG_OVERLAPPED = 0x40000000;
476        public const uint FILE_FLAG_NO_BUFFERING = 0x20000000;
477        public const uint FILE_FLAG_RANDOM_ACCESS = 0x10000000;
478        public const uint FILE_FLAG_SEQUENTIAL_SCAN = 0x08000000;
479        public const uint FILE_FLAG_DELETE_ON_CLOSE = 0x04000000;
480        public const uint FILE_FLAG_BACKUP_SEMANTICS = 0x02000000;
481        public const uint FILE_FLAG_POSIX_SEMANTICS = 0x01000000;
482        public const uint FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000;
483        public const uint FILE_FLAG_OPEN_NO_RECALL = 0x00100000;
484        public const uint FILE_FLAG_FIRST_PIPE_INSTANCE = 0x00080000;
485
486        /// <summary>
487        /// Defines, redefines, or deletes MS-DOS device names.
488        /// </summary>
489        /// <param name="dwFlags">The controllable aspects of the DefineDosDevice function. This
490        /// parameter can be one or more of the DosDeviceDefineFlags.</param>
491        /// <param name="lpDeviceName">A pointer to an MS-DOS device name string specifying the
492        /// device the function is defining, redefining, or deleting. The device name string must
493        /// not have a colon as the last character, unless a drive letter is being defined,
494        /// redefined, or deleted. For example, drive C would be the string "C:". In no case is
495        /// a trailing backslash ("\") allowed.</param>
496        /// <param name="lpTargetPath">A pointer to a path string that will implement this
497        /// device. The string is an MS-DOS path string unless the DDD_RAW_TARGET_PATH flag
498        /// is specified, in which case this string is a path string.</param>
499        /// <returns>If the function succeeds, the return value is true.
500        ///
501        /// If the function fails, the return value is zero. To get extended error
502        /// information, call Marshal.GetLastWin32Error.</returns>
503        [DllImport("Kernel32.dll", SetLastError = true)]
504        [return: MarshalAs(UnmanagedType.Bool)]
505        public extern static bool DefineDosDevice(DosDeviceDefineFlags dwFlags,
506            string lpDeviceName, string lpTargetPath);
507
508        [Flags]
509        public enum DosDeviceDefineFlags
510        {
511            /// <summary>
512            /// If this value is specified along with DDD_REMOVE_DEFINITION, the function will
513            /// use an exact match to determine which mapping to remove. Use this value to
514            /// ensure that you do not delete something that you did not define.
515            /// </summary>
516            ExactMatchOnRmove = 0x00000004,
517
518            /// <summary>
519            /// Do not broadcast the WM_SETTINGCHANGE message. By default, this message is
520            /// broadcast to notify the shell and applications of the change.
521            /// </summary>
522            NoBroadcastSystem = 0x00000008,
523
524            /// <summary>
525            /// Uses the lpTargetPath string as is. Otherwise, it is converted from an MS-DOS
526            /// path to a path.
527            /// </summary>
528            RawTargetPath = 0x00000001,
529
530            /// <summary>
531            /// Removes the specified definition for the specified device. To determine which
532            /// definition to remove, the function walks the list of mappings for the device,
533            /// looking for a match of lpTargetPath against a prefix of each mapping associated
534            /// with this device. The first mapping that matches is the one removed, and then
535            /// the function returns.
536            ///
537            /// If lpTargetPath is NULL or a pointer to a NULL string, the function will remove
538            /// the first mapping associated with the device and pop the most recent one pushed.
539            /// If there is nothing left to pop, the device name will be removed.
540            ///
541            /// If this value is not specified, the string pointed to by the lpTargetPath
542            /// parameter will become the new mapping for this device.
543            /// </summary>
544            RemoveDefinition = 0x00000002
545        }
546
547        /// <summary>
548        /// Retrieves information about MS-DOS device names. The function can obtain the
549        /// current mapping for a particular MS-DOS device name. The function can also obtain
550        /// a list of all existing MS-DOS device names.
551        ///
552        /// MS-DOS device names are stored as junctions in the object name space. The code
553        /// that converts an MS-DOS path into a corresponding path uses these junctions to
554        /// map MS-DOS devices and drive letters. The QueryDosDevice function enables an
555        /// application to query the names of the junctions used to implement the MS-DOS
556        /// device namespace as well as the value of each specific junction.
557        /// </summary>
558        /// <param name="lpDeviceName">An MS-DOS device name string specifying the target of
559        /// the query. The device name cannot have a trailing backslash; for example,
560        /// use "C:", not "C:\".
561        ///
562        /// This parameter can be NULL. In that case, the QueryDosDevice function will
563        /// store a list of all existing MS-DOS device names into the buffer pointed to
564        /// by lpTargetPath.</param>
565        /// <param name="lpTargetPath">A pointer to a buffer that will receive the result
566        /// of the query. The function fills this buffer with one or more null-terminated
567        /// strings. The final null-terminated string is followed by an additional NULL.
568        ///
569        /// If lpDeviceName is non-NULL, the function retrieves information about the
570        /// particular MS-DOS device specified by lpDeviceName. The first null-terminated
571        /// string stored into the buffer is the current mapping for the device. The other
572        /// null-terminated strings represent undeleted prior mappings for the device.
573        ///
574        /// If lpDeviceName is NULL, the function retrieves a list of all existing MS-DOS
575        /// device names. Each null-terminated string stored into the buffer is the name
576        /// of an existing MS-DOS device, for example, \Device\HarddiskVolume1 or
577        /// \Device\Floppy0.</param>
578        /// <param name="length">The maximum number of TCHARs that can be stored into
579        /// the buffer pointed to by lpTargetPath.</param>
580        /// <returns>If the function succeeds, the return value is the number of TCHARs
581        /// stored into the buffer pointed to by lpTargetPath.
582        ///
583        /// If the function fails, the return value is zero. To get extended error
584        /// information, call Marshal.GetLastWin32Error.
585        ///
586        /// If the buffer is too small, the function fails and the last error code is
587        /// ERROR_INSUFFICIENT_BUFFER.</returns>
588        [DllImport("Kernel32.dll", SetLastError = true)]
589        private static extern uint QueryDosDevice([Optional] string lpDeviceName,
590            [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] [Out] char[] lpTargetPath, int length);
591
592        private static string[] QueryDosDeviceInternal(string lpDeviceName)
593        {
594            char[] buffer = new char[32768];
595            for ( ; ; buffer = new char[buffer.Length * 2])
596            {
597                uint written = NativeMethods.QueryDosDevice(lpDeviceName, buffer, buffer.Length);
598
599                //Do we have enough space for all the text
600                if (written != 0)
601                    return ParseNullDelimitedArray(buffer, (int)written);
602                else if (Marshal.GetLastWin32Error() == Win32ErrorCode.InsufficientBuffer)
603                    continue;
604                else
605                    throw Win32ErrorCode.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
606            }
607        }
608
609        public static string QueryDosDevice(string lpDeviceName)
610        {
611            string[] result = QueryDosDeviceInternal(lpDeviceName);
612            return result.Length == 0 ? null : result[0];
613        }
614
615        public static string[] QueryDosDevices()
616        {
617            return QueryDosDeviceInternal(null);
618        }
619
620        [DllImport("Kernel32.dll", SetLastError = true)]
621        [return: MarshalAs(UnmanagedType.Bool)]
622        public extern static bool DeviceIoControl(SafeFileHandle hDevice,
623            uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize,
624            out ushort lpOutBuffer, uint nOutBufferSize, out uint lpBytesReturned,
625            IntPtr lpOverlapped);
626
627        [DllImport("Kernel32.dll", SetLastError = true)]
628        [return: MarshalAs(UnmanagedType.Bool)]
629        public extern static bool DeviceIoControl(SafeFileHandle hDevice,
630            uint dwIoControlCode, ref ushort lpInBuffer, uint nInBufferSize,
631            IntPtr lpOutBuffer, uint nOutBufferSize, out uint lpBytesReturned,
632            IntPtr lpOverlapped);
633
634        public const uint FSCTL_GET_COMPRESSION = 0x9003C;
635        public const uint FSCTL_SET_COMPRESSION = 0x9C040;
636        public const ushort COMPRESSION_FORMAT_NONE = 0x0000;
637        public const ushort COMPRESSION_FORMAT_DEFAULT = 0x0001;
638
639        [DllImport("Kernel32.dll", SetLastError = true)]
640        [return: MarshalAs(UnmanagedType.Bool)]
641        public extern static bool DeviceIoControl(SafeFileHandle hDevice,
642            uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize,
643            IntPtr lpOutBuffer, uint nOutBufferSize, out uint lpBytesReturned,
644            IntPtr lpOverlapped);
645
646        public const uint FSCTL_LOCK_VOLUME = 0x90018;
647        public const uint FSCTL_UNLOCK_VOLUME = 0x9001C;
648
649        [DllImport("Kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
650        [return: MarshalAs(UnmanagedType.Bool)]
651        public static extern bool DeviceIoControl(SafeFileHandle hDevice,
652            uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize,
653            out NTFS_VOLUME_DATA_BUFFER lpOutBuffer, uint nOutBufferSize,
654            out uint lpBytesReturned, IntPtr lpOverlapped);
655
656        /// <summary>
657        /// Retrieves information about the specified NTFS file system volume.
658        /// </summary>
659        public const int FSCTL_GET_NTFS_VOLUME_DATA = (9 << 16) | (25 << 2);
660
661        /// <summary>
662        /// Removes the boot signature from the master boot record, so that the disk will
663        /// be formatted from sector zero to the end of the disk. Partition information
664        /// is no longer stored in sector zero.
665        /// </summary>
666        public const uint IOCTL_DISK_DELETE_DRIVE_LAYOUT =
667            (0x00000007 << 16) | ((0x01 | 0x02) << 14) | (0x0040 << 2);
668
669        [DllImport("Kernel32.dll", SetLastError = true)]
670        [return: MarshalAs(UnmanagedType.Bool)]
671        public extern static bool DeviceIoControl(SafeFileHandle hDevice,
672            uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize,
673            out DiskPerformanceInfoInternal lpOutBuffer, uint nOutBufferSize,
674            out uint lpBytesReturned, IntPtr lpOverlapped);
675
676        public const uint IOCTL_DISK_PERFORMANCE = ((0x00000007) << 16) | ((0x0008) << 2);
677
678        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
679        public struct DiskPerformanceInfoInternal
680        {
681            public long BytesRead;
682            public long BytesWritten;
683            public long ReadTime;
684            public long WriteTime;
685            public long IdleTime;
686            public uint ReadCount;
687            public uint WriteCount;
688            public uint QueueDepth;
689            public uint SplitCount;
690            public long QueryTime;
691            public uint StorageDeviceNumber;
692
693            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
694            public string StorageManagerName;
695        }
696
697        [DllImport("Kernel32.dll", SetLastError = true)]
698        [return: MarshalAs(UnmanagedType.Bool)]
699        public extern static bool DeviceIoControl(SafeFileHandle hDevice,
700            uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize,
701            out long lpOutBuffer, uint nOutBufferSize, out uint lpBytesReturned,
702            IntPtr lpOverlapped);
703
704        /// <summary>
705        /// Retrieves the length of the specified disk, volume, or partition.
706        /// </summary>
707        public const int IOCTL_DISK_GET_LENGTH_INFO =
708            (0x00000007 << 16) | (0x0001 << 14) | (0x0017 << 2);
709
710        /// <summary>
711        /// Retrieves the physical location of a specified volume on one or more disks.
712        /// </summary>
713        public const int IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS =
714            ((0x00000056) << 16) | ((0) << 14) | ((0) << 2) | (0);
715
716        /// <summary>
717        /// Represents a physical location on a disk.
718        /// </summary>
719        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
720        public struct VOLUME_DISK_EXTENTS
721        {
722            /// <summary>
723            /// The number of disks in the volume (a volume can span multiple disks).
724            ///
725            /// An extent is a contiguous run of sectors on one disk. When the number
726            /// of extents returned is greater than one (1), the error code
727            /// ERROR_MORE_DATA is returned. You should call DeviceIoControl again,
728            /// allocating enough buffer space based on the value of NumberOfDiskExtents
729            /// after the first DeviceIoControl call.
730            /// </summary>
731            public uint NumberOfDiskExtents;
732
733            /// <summary>
734            /// The first extent in the set. Subsequent extents are found after this
735            /// structure.
736            /// </summary>
737            public DISK_EXTENT Extent;
738        }
739
740        /// <summary>
741        /// Represents a disk extent.
742        /// </summary>
743        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
744        public struct DISK_EXTENT
745        {
746            /// <summary>
747            /// The number of the disk that contains this extent.
748            ///
749            /// This is the same number that is used to construct the name of the disk,
750            /// for example, the X in PhysicalDriveX or HarddiskX.
751            /// </summary>
752            public uint DiskNumber;
753
754            /// <summary>
755            /// The offset from the beginning of the disk to the extent, in bytes.
756            /// </summary>
757            public long StartingOffset;
758
759            /// <summary>
760            /// The number of bytes in this extent.
761            /// </summary>
762            public long ExtentLength;
763        }
764
765        /// <summary>
766        /// Retrieves a set of FAT file system attributes for a specified file or
767        /// directory.
768        /// </summary>
769        /// <param name="lpFileName">The name of the file or directory.</param>
770        /// <returns>If the function succeeds, the return value contains the attributes
771        /// of the specified file or directory.
772        ///
773        /// If the function fails, the return value is INVALID_FILE_ATTRIBUTES.
774        /// To get extended error information, call Marshal.GetLastWin32Error.
775        ///
776        /// The attributes can be one or more of the FILE_ATTRIBUTE_* values.</returns>
777        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
778        public static extern uint GetFileAttributes(string lpFileName);
779
780        /// <summary>
781        /// Sets the attributes for a file or directory.
782        /// </summary>
783        /// <param name="lpFileName">The name of the file whose attributes are
784        /// to be set.</param>
785        /// <param name="dwFileAttributes">The file attributes to set for the file.
786        /// This parameter can be one or more of the FILE_ATTRIBUTE_* values.
787        /// However, all other values override FILE_ATTRIBUTE_NORMAL.</param>
788        /// <returns>If the function succeeds, the return value is nonzero.
789        ///
790        /// If the function fails, the return value is zero. To get extended error
791        /// information, call Marshal.GetLastWin32Error.</returns>
792        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2205:UseManagedEquivalentsOfWin32Api")]
793        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
794        [return: MarshalAs(UnmanagedType.Bool)]
795        public static extern bool SetFileAttributes(string lpFileName,
796            uint dwFileAttributes);
797
798        /// <summary>
799        /// Retrieves the size of the specified file.
800        /// </summary>
801        /// <param name="hFile">A handle to the file. The handle must have been
802        /// created with either the GENERIC_READ or GENERIC_WRITE access right.
803        /// For more information, see File Security and Access Rights.</param>
804        /// <param name="lpFileSize">A reference to a long that receives the file
805        /// size, in bytes.</param>
806        /// <returns>If the function succeeds, the return value is nonzero.
807        ///
808        /// If the function fails, the return value is zero. To get extended error
809        /// information, call Marshal.GetLastWin32Error.</returns>
810        [DllImport("Kernel32.dll", SetLastError = true)]
811        [return: MarshalAs(UnmanagedType.Bool)]
812        public static extern bool GetFileSizeEx(SafeFileHandle hFile, out long lpFileSize);
813
814        /// <summary>
815        /// Retrieves the date and time that a file or directory was created, last
816        /// accessed, and last modified.
817        /// </summary>
818        /// <param name="hFile">A handle to the file or directory for which dates
819        /// and times are to be retrieved. The handle must have been created using
820        /// the CreateFile function with the GENERIC_READ access right. For more
821        /// information, see File Security and Access Rights.</param>
822        /// <param name="lpCreationTime">A pointer to a FILETIME structure to
823        /// receive the date and time the file or directory was created. This
824        /// parameter can be NULL if the application does not require this
825        /// information.</param>
826        /// <param name="lpLastAccessTime">A pointer to a FILETIME structure to
827        /// receive the date and time the file or directory was last accessed. The
828        /// last access time includes the last time the file or directory was
829        /// written to, read from, or, in the case of executable files, run. This
830        /// parameter can be NULL if the application does not require this
831        /// information.</param>
832        /// <param name="lpLastWriteTime">A pointer to a FILETIME structure to
833        /// receive the date and time the file or directory was last written to,
834        /// truncated, or overwritten (for example, with WriteFile or SetEndOfFile).
835        /// This date and time is not updated when file attributes or security
836        /// descriptors are changed. This parameter can be NULL if the application
837        /// does not require this information.</param>
838        /// <returns>If the function succeeds, the return value is nonzero.
839        ///
840        /// If the function fails, the return value is zero. To get extended error
841        /// information, call Marshal.GetLastWin32Error().</returns>
842        [DllImport("Kernel32.dll", SetLastError = true)]
843        [return: MarshalAs(UnmanagedType.Bool)]
844        public static extern bool GetFileTime(SafeFileHandle hFile,
845            out System.Runtime.InteropServices.ComTypes.FILETIME lpCreationTime,
846            out System.Runtime.InteropServices.ComTypes.FILETIME lpLastAccessTime,
847            out System.Runtime.InteropServices.ComTypes.FILETIME lpLastWriteTime);
848
849        /// <summary>
850        /// Sets the date and time that the specified file or directory was created,
851        /// last accessed, or last modified.
852        /// </summary>
853        /// <param name="hFile">A handle to the file or directory. The handle must
854        /// have been created using the CreateFile function with the
855        /// FILE_WRITE_ATTRIBUTES access right. For more information, see File
856        /// Security and Access Rights.</param>
857        /// <param name="lpCreationTime">A pointer to a FILETIME structure that
858        /// contains the new creation date and time for the file or directory.
859        /// This parameter can be NULL if the application does not need to change
860        /// this information.</param>
861        /// <param name="lpLastAccessTime">A pointer to a FILETIME structure that
862        /// contains the new last access date and time for the file or directory.
863        /// The last access time includes the last time the file or directory was
864        /// written to, read from, or (in the case of executable files) run. This
865        /// parameter can be NULL if the application does not need to change this
866        /// information.
867        ///
868        /// To preserve the existing last access time for a file even after accessing
869        /// a file, call SetFileTime immediately after opening the file handle
870        /// with this parameter's FILETIME structure members initialized to
871        /// 0xFFFFFFFF.</param>
872        /// <param name="lpLastWriteTime">A pointer to a FILETIME structure that
873        /// contains the new last modified date and time for the file or directory.
874        /// This parameter can be NULL if the application does not need to change
875        /// this information.</param>
876        /// <returns>If the function succeeds, the return value is nonzero.
877        ///
878        /// If the function fails, the return value is zero. To get extended error
879        /// information, call GetLastError.</returns>
880        [DllImport("Kernel32.dll", SetLastError = true)]
881        [return: MarshalAs(UnmanagedType.Bool)]
882        public static extern bool SetFileTime(SafeFileHandle hFile,
883            ref System.Runtime.InteropServices.ComTypes.FILETIME lpCreationTime,
884            ref System.Runtime.InteropServices.ComTypes.FILETIME lpLastAccessTime,
885            ref System.Runtime.InteropServices.ComTypes.FILETIME lpLastWriteTime);
886
887        /// <summary>
888        /// Retrieves the name of a volume on a computer. FindFirstVolume is used
889        /// to begin scanning the volumes of a computer.
890        /// </summary>
891        /// <param name="lpszVolumeName">A pointer to a buffer that receives a
892        /// null-terminated string that specifies the unique volume name of the
893        /// first volume found.</param>
894        /// <param name="cchBufferLength">The length of the buffer to receive the
895        /// name, in TCHARs.</param>
896        /// <returns>If the function succeeds, the return value is a search handle
897        /// used in a subsequent call to the FindNextVolume and FindVolumeClose
898        /// functions.
899        ///
900        /// If the function fails to find any volumes, the return value is the
901        /// INVALID_HANDLE_VALUE error code. To get extended error information,
902        /// call GetLastError.</returns>
903        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
904        public static extern SafeFileHandle FindFirstVolume(StringBuilder lpszVolumeName,
905            uint cchBufferLength);
906
907        /// <summary>
908        /// Continues a volume search started by a call to the FindFirstVolume
909        /// function. FindNextVolume finds one volume per call.
910        /// </summary>
911        /// <param name="hFindVolume">The volume search handle returned by a previous
912        /// call to the FindFirstVolume function.</param>
913        /// <param name="lpszVolumeName">A pointer to a string that receives the
914        /// unique volume name found.</param>
915        /// <param name="cchBufferLength">The length of the buffer that receives
916        /// the name, in TCHARs.</param>
917        /// <returns>If the function succeeds, the return value is nonzero.
918        ///
919        /// If the function fails, the return value is zero. To get extended error
920        /// information, call GetLastError. If no matching files can be found, the
921        /// GetLastError function returns the ERROR_NO_MORE_FILES error code. In
922        /// that case, close the search with the FindVolumeClose function.</returns>
923        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
924        [return: MarshalAs(UnmanagedType.Bool)]
925        public static extern bool FindNextVolume(SafeHandle hFindVolume,
926            StringBuilder lpszVolumeName, uint cchBufferLength);
927
928        /// <summary>
929        /// Closes the specified volume search handle. The FindFirstVolume and
930        /// FindNextVolume functions use this search handle to locate volumes.
931        /// </summary>
932        /// <param name="hFindVolume">The volume search handle to be closed. This
933        /// handle must have been previously opened by the FindFirstVolume function.</param>
934        /// <returns>If the function succeeds, the return value is nonzero.
935        ///
936        /// If the function fails, the return value is zero. To get extended error
937        /// information, call GetLastError.</returns>
938        [DllImport("Kernel32.dll", SetLastError = true)]
939        [return: MarshalAs(UnmanagedType.Bool)]
940        public static extern bool FindVolumeClose(SafeHandle hFindVolume);
941
942        /// <summary>
943        /// Retrieves the name of a volume mount point on the specified volume.
944        /// FindFirstVolumeMountPoint is used to begin scanning the volume mount
945        /// points on a volume.
946        /// </summary>
947        /// <param name="lpszRootPathName">The unique volume name of the volume
948        /// to scan for volume mount points. A trailing backslash is required.</param>
949        /// <param name="lpszVolumeMountPoint">A pointer to a buffer that receives
950        /// the name of the first volume mount point found.</param>
951        /// <param name="cchBufferLength">The length of the buffer that receives
952        /// the volume mount point name, in TCHARs.</param>
953        /// <returns>If the function succeeds, the return value is a search handle
954        /// used in a subsequent call to the FindNextVolumeMountPoint and
955        /// FindVolumeMountPointClose functions.
956        ///
957        /// If the function fails to find a volume mount point on the volume, the
958        /// return value is the INVALID_HANDLE_VALUE error code. To get extended
959        /// error information, call GetLastError.</returns>
960        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
961        public static extern SafeFileHandle FindFirstVolumeMountPoint(
962            string lpszRootPathName, StringBuilder lpszVolumeMountPoint,
963            uint cchBufferLength);
964
965        /// <summary>
966        /// Continues a volume mount point search started by a call to the
967        /// FindFirstVolumeMountPoint function. FindNextVolumeMountPoint finds one
968        /// volume mount point per call.
969        /// </summary>
970        /// <param name="hFindVolumeMountPoint">A mount-point search handle returned
971        /// by a previous call to the FindFirstVolumeMountPoint function.</param>
972        /// <param name="lpszVolumeMountPoint">A pointer to a buffer that receives
973        /// the name of the volume mount point found.</param>
974        /// <param name="cchBufferLength">The length of the buffer that receives
975        /// the names, in TCHARs.</param>
976        /// <returns>If the function succeeds, the return value is nonzero.
977        ///
978        /// If the function fails, the return value is zero. To get extended error
979        /// information, call GetLastError. If no matching files can be found, the
980        /// GetLastError function returns the ERROR_NO_MORE_FILES error code. In
981        /// that case, close the search with the FindVolumeMountPointClose function.</returns>
982        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
983        [return: MarshalAs(UnmanagedType.Bool)]
984        public static extern bool FindNextVolumeMountPoint(
985            SafeHandle hFindVolumeMountPoint, StringBuilder lpszVolumeMountPoint,
986            uint cchBufferLength);
987
988        /// <summary>
989        /// Closes the specified mount-point search handle. The FindFirstVolumeMountPoint
990        /// and FindNextVolumeMountPoint  functions use this search handle to locate
991        /// volume mount points on a specified volume.
992        /// </summary>
993        /// <param name="hFindVolumeMountPoint">The mount-point search handle to
994        /// be closed. This handle must have been previously opened by the
995        /// FindFirstVolumeMountPoint function.</param>
996        /// <returns>If the function succeeds, the return value is nonzero.
997        ///
998        /// If the function fails, the return value is zero. To get extended error
999        /// information, call GetLastError.</returns>
1000        [DllImport("Kernel32.dll", SetLastError = true)]
1001        [return: MarshalAs(UnmanagedType.Bool)]
1002        public static extern bool FindVolumeMountPointClose(SafeHandle hFindVolumeMountPoint);
1003
1004        /// <summary>
1005        /// Retrieves information about the specified disk, including the amount
1006        /// of free space on the disk.
1007        ///
1008        /// The GetDiskFreeSpace function cannot report volume sizes that are
1009        /// greater than 2 gigabytes (GB). To ensure that your application works
1010        /// with large capacity hard drives, use the GetDiskFreeSpaceEx function.
1011        /// </summary>
1012        /// <param name="lpRootPathName">The root directory of the disk for which
1013        /// information is to be returned. If this parameter is NULL, the function
1014        /// uses the root of the current disk. If this parameter is a UNC name,
1015        /// it must include a trailing backslash (for example, \\MyServer\MyShare\).
1016        /// Furthermore, a drive specification must have a trailing backslash
1017        /// (for example, C:\). The calling application must have FILE_LIST_DIRECTORY
1018        /// access rights for this directory.</param>
1019        /// <param name="lpSectorsPerCluster">A pointer to a variable that receives
1020        /// the number of sectors per cluster.</param>
1021        /// <param name="lpBytesPerSector">A pointer to a variable that receives
1022        /// the number of bytes per sector.</param>
1023        /// <param name="lpNumberOfFreeClusters">A pointer to a variable that
1024        /// receives the total number of free clusters on the disk that are
1025        /// available to the user who is associated with the calling thread.
1026        ///
1027        /// If per-user disk quotas are in use, this value may be less than the
1028        /// total number of free clusters on the disk.</param>
1029        /// <param name="lpTotalNumberOfClusters">A pointer to a variable that
1030        /// receives the total number of clusters on the disk that are available
1031        /// to the user who is associated with the calling thread.
1032        ///
1033        /// If per-user disk quotas are in use, this value may be less than the
1034        /// total number of clusters on the disk.</param>
1035        /// <returns>If the function succeeds, the return value is true. To get
1036        /// extended error information, call Marshal.GetLastWin32Error().</returns>
1037        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
1038        [return: MarshalAs(UnmanagedType.Bool)]
1039        public static extern bool GetDiskFreeSpace(
1040            string lpRootPathName, out UInt32 lpSectorsPerCluster, out UInt32 lpBytesPerSector,
1041            out UInt32 lpNumberOfFreeClusters, out UInt32 lpTotalNumberOfClusters);
1042
1043
1044        /// <summary>
1045        /// Retrieves information about the amount of space that is available on
1046        /// a disk volume, which is the total amount of space, the total amount
1047        /// of free space, and the total amount of free space available to the
1048        /// user that is associated with the calling thread.
1049        /// </summary>
1050        /// <param name="lpDirectoryName">A directory on the disk.
1051        ///
1052        /// If this parameter is NULL, the function uses the root of the current
1053        /// disk.
1054        ///
1055        /// If this parameter is a UNC name, it must include a trailing backslash,
1056        /// for example, "\\MyServer\MyShare\".
1057        ///
1058        /// This parameter does not have to specify the root directory on a disk.
1059        /// The function accepts any directory on a disk.
1060        ///
1061        /// The calling application must have FILE_LIST_DIRECTORY access rights
1062        /// for this directory.</param>
1063        /// <param name="lpFreeBytesAvailable">A pointer to a variable that receives
1064        /// the total number of free bytes on a disk that are available to the
1065        /// user who is associated with the calling thread.
1066        ///
1067        /// This parameter can be NULL.
1068        ///
1069        /// If per-user quotas are being used, this value may be less than the
1070        /// total number of free bytes on a disk.</param>
1071        /// <param name="lpTotalNumberOfBytes">A pointer to a variable that receives
1072        /// the total number of bytes on a disk that are available to the user who
1073        /// is associated with the calling thread.
1074        ///
1075        /// This parameter can be NULL.
1076        ///
1077        /// If per-user quotas are being used, this value may be less than the
1078        /// total number of bytes on a disk.
1079        ///
1080        /// To determine the total number of bytes on a disk or volume, use
1081        /// IOCTL_DISK_GET_LENGTH_INFO.</param>
1082        /// <param name="lpTotalNumberOfFreeBytes">A pointer to a variable that
1083        /// receives the total number of free bytes on a disk.
1084        ///
1085        /// This parameter can be NULL.</param>
1086        /// <returns>If the function succeeds, the return value is nonzero.
1087        ///
1088        /// If the function fails, the return value is zero (0). To get extended
1089        /// error information, call GetLastError.</returns>
1090        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
1091        [return: MarshalAs(UnmanagedType.Bool)]
1092        public static extern bool GetDiskFreeSpaceEx(
1093            string lpDirectoryName,
1094            out UInt64 lpFreeBytesAvailable,
1095            out UInt64 lpTotalNumberOfBytes,
1096            out UInt64 lpTotalNumberOfFreeBytes);
1097
1098        /// <summary>
1099        /// Determines whether a disk drive is a removable, fixed, CD-ROM, RAM disk,
1100        /// or network drive.
1101        /// </summary>
1102        /// <param name="lpRootPathName">The root directory for the drive.
1103        ///
1104        /// A trailing backslash is required. If this parameter is NULL, the function
1105        /// uses the root of the current directory.</param>
1106        /// <returns>The return value specifies the type of drive, which can be
1107        /// one of the DriveInfo.DriveType values.</returns>
1108        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
1109        public static extern uint GetDriveType(string lpRootPathName);
1110
1111        /// <summary>
1112        /// Retrieves information about the file system and volume associated with
1113        /// the specified root directory.
1114        ///
1115        /// To specify a handle when retrieving this information, use the
1116        /// GetVolumeInformationByHandleW function.
1117        ///
1118        /// To retrieve the current compression state of a file or directory, use
1119        /// FSCTL_GET_COMPRESSION.
1120        /// </summary>
1121        /// <param name="lpRootPathName">    A pointer to a string that contains
1122        /// the root directory of the volume to be described.
1123        ///
1124        /// If this parameter is NULL, the root of the current directory is used.
1125        /// A trailing backslash is required. For example, you specify
1126        /// \\MyServer\MyShare as "\\MyServer\MyShare\", or the C drive as "C:\".</param>
1127        /// <param name="lpVolumeNameBuffer">A pointer to a buffer that receives
1128        /// the name of a specified volume. The maximum buffer size is MAX_PATH+1.</param>
1129        /// <param name="nVolumeNameSize">The length of a volume name buffer, in
1130        /// TCHARs. The maximum buffer size is MAX_PATH+1.
1131        ///
1132        /// This parameter is ignored if the volume name buffer is not supplied.</param>
1133        /// <param name="lpVolumeSerialNumber">A pointer to a variable that receives
1134        /// the volume serial number.
1135        ///
1136        /// This parameter can be NULL if the serial number is not required.
1137        ///
1138        /// This function returns the volume serial number that the operating system
1139        /// assigns when a hard disk is formatted. To programmatically obtain the
1140        /// hard disk's serial number that the manufacturer assigns, use the
1141        /// Windows Management Instrumentation (WMI) Win32_PhysicalMedia property
1142        /// SerialNumber.</param>
1143        /// <param name="lpMaximumComponentLength">A pointer to a variable that
1144        /// receives the maximum length, in TCHARs, of a file name component that
1145        /// a specified file system supports.
1146        ///
1147        /// A file name component is the portion of a file name between backslashes.
1148        ///
1149        /// The value that is stored in the variable that *lpMaximumComponentLength
1150        /// points to is used to indicate that a specified file system supports
1151        /// long names. For example, for a FAT file system that supports long names,
1152        /// the function stores the value 255, rather than the previous 8.3 indicator.
1153        /// Long names can also be supported on systems that use the NTFS file system.</param>
1154        /// <param name="lpFileSystemFlags">A pointer to a variable that receives
1155        /// flags associated with the specified file system.
1156        ///
1157        /// This parameter can be one or more of the FS_FILE* flags. However,
1158        /// FS_FILE_COMPRESSION and FS_VOL_IS_COMPRESSED are mutually exclusive.</param>
1159        /// <param name="lpFileSystemNameBuffer">A pointer to a buffer that receives
1160        /// the name of the file system, for example, the FAT file system or the
1161        /// NTFS file system. The maximum buffer size is MAX_PATH+1.</param>
1162        /// <param name="nFileSystemNameSize">The length of the file system name
1163        /// buffer, in TCHARs. The maximum buffer size is MAX_PATH+1.
1164        ///
1165        /// This parameter is ignored if the file system name buffer is not supplied.</param>
1166        /// <returns>If all the requested information is retrieved, the return value
1167        /// is nonzero.
1168        ///
1169        ///
1170        /// If not all the requested information is retrieved, the return value is
1171        /// zero (0). To get extended error information, call GetLastError.</returns>
1172        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
1173        [return: MarshalAs(UnmanagedType.Bool)]
1174        public static extern bool GetVolumeInformation(
1175            string lpRootPathName,
1176            StringBuilder lpVolumeNameBuffer,
1177            uint nVolumeNameSize,
1178            out uint lpVolumeSerialNumber,
1179            out uint lpMaximumComponentLength,
1180            out uint lpFileSystemFlags,
1181            StringBuilder lpFileSystemNameBuffer,
1182            uint nFileSystemNameSize);
1183
1184        /// <summary>
1185        /// Retrieves the unique volume name for the specified volume mount point or root directory.
1186        /// </summary>
1187        /// <param name="lpszVolumeMountPoint">The path of a volume mount point (with a trailing
1188        /// backslash, "\") or a drive letter indicating a root directory (in the
1189        /// form "D:\").</param>
1190        /// <param name="lpszVolumeName">A pointer to a string that receives the
1191        /// volume name. This name is a unique volume name of the form
1192        /// "\\?\Volume{GUID}\" where GUID is the GUID that identifies the volume.</param>
1193        /// <param name="cchBufferLength">The length of the output buffer, in TCHARs.
1194        /// A reasonable size for the buffer to accommodate the largest possible
1195        /// volume name is 50 characters.</param>
1196        /// <returns>If the function succeeds, the return value is nonzero.
1197        ///
1198        /// If the function fails, the return value is zero. To get extended
1199        /// error information, call GetLastError.</returns>
1200        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
1201        [return: MarshalAs(UnmanagedType.Bool)]
1202        public static extern bool GetVolumeNameForVolumeMountPoint(
1203            string lpszVolumeMountPoint, StringBuilder lpszVolumeName,
1204            uint cchBufferLength);
1205
1206        /// <summary>
1207        /// Retrieves a list of path names for the specified volume name.
1208        /// </summary>
1209        /// <param name="lpszVolumeName">The volume name.</param>
1210        /// <param name="lpszVolumePathNames">A pointer to a buffer that receives
1211        /// the list of volume path names. The list is an array of null-terminated
1212        /// strings terminated by an additional NULL character. If the buffer is
1213        /// not large enough to hold the complete list, the buffer holds as much
1214        /// of the list as possible.</param>
1215        /// <param name="cchBufferLength">The length of the lpszVolumePathNames
1216        /// buffer, in TCHARs.</param>
1217        /// <param name="lpcchReturnLength">If the call is successful, this parameter
1218        /// is the number of TCHARs copied to the lpszVolumePathNames buffer. Otherwise,
1219        /// this parameter is the size of the buffer required to hold the complete
1220        /// list, in TCHARs.</param>
1221        /// <returns></returns>
1222        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
1223        [return: MarshalAs(UnmanagedType.Bool)]
1224        private static extern bool GetVolumePathNamesForVolumeName(string lpszVolumeName,
1225            [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] char[] lpszVolumePathNames,
1226            uint cchBufferLength, out uint lpcchReturnLength);
1227
1228        /// <summary>
1229        /// Retrieves a list of path names for the specified volume name.
1230        /// </summary>
1231        /// <param name="lpszVolumeName">The volume name.</param>
1232        public static string[] GetVolumePathNamesForVolumeName(string lpszVolumeName)
1233        {
1234            uint returnLength = 0;
1235            char[] pathNamesBuffer = new char[NativeMethods.MaxPath];
1236            while (!NativeMethods.GetVolumePathNamesForVolumeName(lpszVolumeName,
1237                pathNamesBuffer, (uint)pathNamesBuffer.Length, out returnLength))
1238            {
1239                int errorCode = Marshal.GetLastWin32Error();
1240                switch (errorCode)
1241                {
1242                    case Win32ErrorCode.NotReady:
1243                        //The drive isn't ready yet: just return an empty list.
1244                        return new string[0];
1245                    case Win32ErrorCode.MoreData:
1246                        pathNamesBuffer = new char[pathNamesBuffer.Length * 2];
1247                        break;
1248                    default:
1249                        throw Win32ErrorCode.GetExceptionForWin32Error(errorCode);
1250                }
1251            }
1252
1253            return ParseNullDelimitedArray(pathNamesBuffer, (int)returnLength);
1254        }
1255
1256        public const int MaxPath = 260;
1257        public const int LongPath = 32768;
1258
1259        /// <summary>
1260        /// Retrieves the product type for the operating system on the local computer, and
1261        /// maps the type to the product types supported by the specified operating system.
1262        /// </summary>
1263        /// <param name="dwOSMajorVersion">The major version number of the operating system.
1264        /// The minimum value is 6.
1265        ///
1266        /// The combination of the dwOSMajorVersion, dwOSMinorVersion, dwSpMajorVersion,
1267        /// and dwSpMinorVersion parameters describes the maximum target operating system
1268        /// version for the application. For example, Windows Vista and Windows Server
1269        /// 2008 are version 6.0.0.0 and Windows 7 and Windows Server 2008 R2 are version
1270        /// 6.1.0.0.</param>
1271        /// <param name="dwOSMinorVersion">The minor version number of the operating
1272        /// system. The minimum value is 0.</param>
1273        /// <param name="dwSpMajorVersion">The major version number of the operating
1274        /// system service pack. The minimum value is 0.</param>
1275        /// <param name="dwSpMinorVersion">The minor version number of the operating
1276        /// system service pack. The minimum value is 0.</param>
1277        /// <param name="pdwReturnedProductType">The product type. This parameter
1278        /// cannot be NULL. If the specified operating system is less than the
1279        /// current operating system, this information is mapped to the types
1280        /// supported by the specified operating system. If the specified operating
1281        /// system is greater than the highest supported operating system, this
1282        /// information is mapped to the types supported by the current operating system.
1283        ///
1284        /// If the product has not been activated and is no longer in the grace period,
1285        /// this parameter is set to PRODUCT_UNLICENSED (0xABCDABCD).</param>
1286        /// <returns>If the function succeeds, the return value is a nonzero value.
1287        /// If the software license is invalid or expired, the function succeeds
1288        /// but the pdwReturnedProductType parameter is set to PRODUCT_UNLICENSED.
1289        ///
1290        /// If the function fails, the return value is zero. This function fails if
1291        /// one of the input parameters is invalid.</returns>
1292        [DllImport("Kernel32.dll", CharSet = CharSet.Unicode)]
1293        public static extern bool GetProductInfo(uint dwOSMajorVersion,
1294            uint dwOSMinorVersion, uint dwSpMajorVersion, uint dwSpMinorVersion,
1295            out WindowsEditions pdwReturnedProductType);
1296
1297        /// <summary>
1298        /// Frees the specified local memory object and invalidates its handle.
1299        /// </summary>
1300        /// <param name="hMem">A handle to the local memory object. This handle is
1301        /// returned by either the LocalAlloc or LocalReAlloc function. It is not
1302        /// safe to free memory allocated with GlobalAlloc.</param>
1303        /// <returns>If the function succeeds, the return value is NULL.
1304        ///
1305        /// If the function fails, the return value is equal to a handle to the
1306        /// local memory object. To get extended error information, call
1307        /// GetLastError.</returns>
1308        /// <remarks>If the process tries to examine or modify the memory after
1309        /// it has been freed, heap corruption may occur or an access violation
1310        /// exception (EXCEPTION_ACCESS_VIOLATION) may be generated.
1311        ///
1312        /// If the hMem parameter is NULL, LocalFree ignores the parameter and
1313        /// returns NULL.
1314        ///
1315        /// The LocalFree function will free a locked memory object. A locked
1316        /// memory object has a lock count greater than zero. The LocalLock
1317        /// function locks a local memory object and increments the lock count
1318        /// by one. The LocalUnlock function unlocks it and decrements the lock
1319        /// count by one. To get the lock count of a local memory object, use
1320        /// the LocalFlags function.
1321        ///
1322        /// If an application is running under a debug version of the system,
1323        /// LocalFree will issue a message that tells you that a locked object
1324        /// is being freed. If you are debugging the application, LocalFree will
1325        /// enter a breakpoint just before freeing a locked object. This allows
1326        /// you to verify the intended behavior, then continue execution.</remarks>
1327        [DllImport("Kernel32.dll", SetLastError = true)]
1328        public static extern IntPtr LocalFree(IntPtr hMem);
1329
1330        /// <summary>
1331        /// Parses a null-delimited array into a string array.
1332        /// </summary>
1333        /// <param name="buffer">The buffer to parse.</param>
1334        /// <param name="length">The valid length of the array.</param>
1335        /// <returns>The array found in the buffer</returns>
1336        private static string[] ParseNullDelimitedArray(char[] buffer, int length)
1337        {
1338            List<string> result = new List<string>();
1339            for (int lastIndex = 0, i = 0; i != length; ++i)
1340            {
1341                if (buffer[i] == '\0')
1342                {
1343                    //If the string formed is empty, there are no elements left.
1344                    if (i - lastIndex == 0)
1345                        break;
1346
1347                    result.Add(new string(buffer, lastIndex, i - lastIndex));
1348
1349                    lastIndex = i + 1;
1350                    if (buffer[lastIndex] == '\0')
1351                        break;
1352                }
1353            }
1354
1355            return result.ToArray();
1356        }
1357    }
1358}
Note: See TracBrowser for help on using the repository browser.