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

Revision 2515, 62.6 KB checked in by lowjoel, 2 years ago (diff)

Set svn:keywords and svn:eol-style on all the source files.

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