source: branches/eraser6/Util/Drive.cs @ 404

Revision 404, 28.3 KB checked in by lowjoel, 6 years ago (diff)

-Always use Marshal.PtrToStringUni? since we are specifically using the Unicode functions
-Implement almost all the other members of System.IO.DriveInfo?, for drop-in replacement in Eraser
-Added the Volume.FromMountpoint? function to create a Volume object from the path to the mount point or Drive (since the constructor takes a volume ID, unlike the usual DriveInfo? function)
-Changed the Get functions to properties since we are a full class now

  • Property svn:keywords set to Id
Line 
1/*
2 * $Id$
3 * Copyright 2008 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;
25
26using System.Runtime.InteropServices;
27using System.ComponentModel;
28using System.IO;
29using Microsoft.Win32.SafeHandles;
30
31namespace Eraser.Util
32{
33    public class Volume
34    {
35        /// <summary>
36        /// Constructor.
37        /// </summary>
38        /// <param name="volumeID">The ID of the volume, in the form "\\?\Volume{GUID}\"</param>
39        public Volume(string volumeID)
40        {
41            //Set the volume Id
42            this.volumeID = volumeID;
43
44            //Get the paths of the said volume
45            IntPtr pathNamesBuffer = IntPtr.Zero;
46            string pathNames = string.Empty;
47            try
48            {
49                uint currentBufferSize = MaxPath;
50                uint returnLength = 0;
51                pathNamesBuffer = Marshal.AllocHGlobal((int)(currentBufferSize * sizeof(char)));
52                while (!GetVolumePathNamesForVolumeName(volumeID, pathNamesBuffer, currentBufferSize,
53                    out returnLength))
54                {
55                    if (Marshal.GetLastWin32Error() == 234/*ERROR_MORE_DATA*/)
56                    {
57                        currentBufferSize *= 2;
58                        pathNamesBuffer = Marshal.AllocHGlobal((int)(currentBufferSize * sizeof(char)));
59                    }
60                    else
61                        throw new Win32Exception(Marshal.GetLastWin32Error(),
62                            "Eraser.Util.Volume.Volume");
63                }
64
65                pathNames = Marshal.PtrToStringUni(pathNamesBuffer, (int)returnLength);
66            }
67            finally
68            {
69                if (pathNamesBuffer != IntPtr.Zero)
70                    Marshal.FreeHGlobal(pathNamesBuffer);
71            }
72
73            //OK, the marshalling is complete. Convert the pathNames string into a list
74            //of strings containing all of the volumes mountpoints; because the
75            //GetVolumePathNamesForVolumeName function returns a convoluted structure
76            //containing the path names.
77            for (int lastIndex = 0, i = 0; i != pathNames.Length; ++i)
78            {
79                if (pathNames[i] == '\0')
80                {
81                    mountPoints.Add(pathNames.Substring(lastIndex, i - lastIndex));
82
83                    lastIndex = i + 1;
84                    if (pathNames[lastIndex] == '\0')
85                        break;
86                }
87            }
88
89            //Fill up the remaining members of the structure: file system, label, etc.
90            IntPtr volumeName = Marshal.AllocHGlobal(MaxPath * sizeof(char)),
91                   fileSystemName = Marshal.AllocHGlobal(MaxPath * sizeof(char));
92            try
93            {
94                uint serialNumber, maxComponentLength, filesystemFlags;
95                if (!GetVolumeInformation(volumeID, volumeName, MaxPath, out serialNumber,
96                    out maxComponentLength, out filesystemFlags, fileSystemName, MaxPath))
97                {
98                    if (Marshal.GetLastWin32Error() != 21 /*ERROR_NOT_READY*/)
99                        throw new Win32Exception(Marshal.GetLastWin32Error(), "Eraser.Util.Volume.Volume");
100                }
101                else
102                {
103                    //OK, the volume information's queried, store what we know.
104                    driveFormat = Marshal.PtrToStringUni(fileSystemName);
105                    volumeLabel = Marshal.PtrToStringUni(volumeName);
106                    isReady = true;
107                }
108            }
109            finally
110            {
111                Marshal.FreeHGlobal(volumeName);
112                Marshal.FreeHGlobal(fileSystemName);
113            }
114        }
115
116        /// <summary>
117        /// Lists all the volumes in the system.
118        /// </summary>
119        /// <returns>Returns a list of volumes representing all volumes present in
120        /// the system.</returns>
121        public static List<Volume> GetVolumes()
122        {
123            List<Volume> result = new List<Volume>();
124            IntPtr nextVolume = Marshal.AllocHGlobal(LongPath * sizeof(char));
125            try
126            {
127                SafeHandle handle = FindFirstVolume(nextVolume, LongPath);
128                if (handle.IsInvalid)
129                    return result;
130
131                //Iterate over the volume mountpoints
132                do
133                    result.Add(new Volume(Marshal.PtrToStringUni(nextVolume)));
134                while (FindNextVolume(handle, nextVolume, LongPath));
135
136                //Close the handle
137                if (Marshal.GetLastWin32Error() == 18 /*ERROR_NO_MORE_FILES*/)
138                    FindVolumeClose(handle);
139               
140                return result;
141            }
142            finally
143            {
144                Marshal.FreeHGlobal(nextVolume);
145            }
146        }
147
148        /// <summary>
149        /// Creates a Volume object from its mountpoint.
150        /// </summary>
151        /// <param name="mountpoint">The path to the mountpoint.</param>
152        /// <returns>The volume object if such a volume exists, or an exception
153        /// is thrown.</returns>
154        public static Volume FromMountpoint(string mountpoint)
155        {
156            DirectoryInfo mountpointDir = new DirectoryInfo(mountpoint);
157            IntPtr volumeID = Marshal.AllocHGlobal(50 * sizeof(char));
158            try
159            {
160                do
161                {
162                    string currentDir = mountpointDir.FullName;
163                    if (currentDir.Length > 0 && currentDir[currentDir.Length - 1] != '\\')
164                        currentDir += '\\';
165                    if (GetVolumeNameForVolumeMountPoint(currentDir, volumeID, 50))
166                        return new Volume(Marshal.PtrToStringUni(volumeID));
167                    else if (Marshal.GetLastWin32Error() != 4390 /*ERROR_NOT_A_REPARSE_POINT*/)
168                        throw new Win32Exception(Marshal.GetLastWin32Error());
169                    mountpointDir = mountpointDir.Parent;
170                }
171                while (mountpointDir != null);
172
173                throw new Win32Exception(4390 /*ERROR_NOT_A_REPARSE_POINT*/);
174            }
175            finally
176            {
177                Marshal.FreeHGlobal(volumeID);
178            }
179        }
180
181        /// <summary>
182        /// Returns the volume identifier as would be returned from FindFirstVolume.
183        /// </summary>
184        public string VolumeID
185        {
186            get { return volumeID; }
187        }
188        private string volumeID;
189
190        /// <summary>
191        /// Gets or sets the volume label of a drive.
192        /// </summary>
193        public string VolumeLabel
194        {
195            get { return VolumeLabel; }
196            set { throw new NotImplementedException();  }
197        }
198        private string volumeLabel;
199
200        /// <summary>
201        /// Gets the name of the file system, such as NTFS or FAT32.
202        /// </summary>
203        public string VolumeFormat
204        {
205            get
206            {
207                return driveFormat;
208            }
209        }
210        private string driveFormat;
211
212        /// <summary>
213        /// Gets the drive type; returns one of the System.IO.DriveType values.
214        /// </summary>
215        public DriveType VolumeType
216        {
217            get
218            {
219                return (DriveType)GetDriveType(VolumeID);
220            }
221        }
222
223        /// <summary>
224        /// Determines the cluster size of the current volume.
225        /// </summary>
226        public int ClusterSize
227        {
228            get
229            {
230                uint clusterSize, sectorSize, freeClusters, totalClusters;
231                if (GetDiskFreeSpace(volumeID, out clusterSize, out sectorSize,
232                    out freeClusters, out totalClusters))
233                    return (int)(clusterSize * sectorSize);
234
235                throw new Win32Exception(Marshal.GetLastWin32Error(),
236                    "Eraser.Util.Drive.GetClusterSize");
237            }
238        }
239
240        /// <summary>
241        /// Checks if the current user has disk quotas on the current volume.
242        /// </summary>
243        public bool HasQuota
244        {
245            get
246            {
247                ulong freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes;
248                if (GetDiskFreeSpaceEx(volumeID, out freeBytesAvailable, out totalNumberOfBytes,
249                    out totalNumberOfFreeBytes))
250                    return totalNumberOfFreeBytes != freeBytesAvailable;
251
252                throw new Win32Exception(Marshal.GetLastWin32Error(),
253                    "Eraser.Util.Drive.HasQuota");
254            }
255        }
256
257        /// <summary>
258        /// Gets a value indicating whether a drive is ready.
259        /// </summary>
260        public bool IsReady
261        {
262            get { return isReady; }
263        }
264        private bool isReady = false;
265
266        /// <summary>
267        /// Gets the total amount of free space available on a drive.
268        /// </summary>
269        public long TotalFreeSpace
270        {
271            get
272            {
273                ulong result, dummy;
274                if (GetDiskFreeSpaceEx(volumeID, out dummy, out dummy, out result))
275                    return (long)result;
276
277                throw new Win32Exception(Marshal.GetLastWin32Error(),
278                    "Eraser.Util.Drive.TotalFreeSpace");
279            }
280        }
281       
282        /// <summary>
283        /// Gets the total size of storage space on a drive.
284        /// </summary>
285        public long TotalSize
286        {
287            get
288            {
289                UInt64 result, dummy;
290                if (GetDiskFreeSpaceEx(volumeID, out dummy, out result, out dummy))
291                    return (long)result;
292
293                throw new Win32Exception(Marshal.GetLastWin32Error(),
294                    "Eraser.Util.Drive.TotalSize");
295            }
296        }
297
298        /// <summary>
299        /// Indicates the amount of available free space on a drive.
300        /// </summary>
301        public long AvailableFreeSpace
302        {
303            get
304            {
305                UInt64 result, dummy;
306                if (GetDiskFreeSpaceEx(volumeID, out result, out dummy, out dummy))
307                    return (long)result;
308
309                throw new Win32Exception(Marshal.GetLastWin32Error(),
310                    "Eraser.Util.Drive.AvailableFreeSpace");
311            }
312        }
313
314        /// <summary>
315        /// Retrieves all mountpoints in the current volume, if the current volume
316        /// contains volume mountpoints.
317        /// </summary>
318        public List<Volume> MountedVolumes
319        {
320            get
321            {
322                List<Volume> result = new List<Volume>();
323                IntPtr nextMountpoint = Marshal.AllocHGlobal(LongPath * sizeof(char));
324                try
325                {
326                    SafeHandle handle = FindFirstVolumeMountPoint(VolumeID,
327                        nextMountpoint, LongPath);
328                    if (handle.IsInvalid)
329                        return result;
330
331                    //Iterate over the volume mountpoints
332                    while (FindNextVolumeMountPoint(handle, nextMountpoint, LongPath))
333                        result.Add(new Volume(Marshal.PtrToStringUni(nextMountpoint)));
334
335                    //Close the handle
336                    if (Marshal.GetLastWin32Error() == 18 /*ERROR_NO_MORE_FILES*/)
337                        FindVolumeMountPointClose(handle);
338
339                    return result;
340                }
341                finally
342                {
343                    Marshal.FreeHGlobal(nextMountpoint);
344                }
345            }
346        }
347
348        /// <summary>
349        /// The various mountpoints to the root of the volume. This list contains
350        /// paths which may be a drive or a mountpoint. Every string includes the
351        /// trailing backslash.
352        /// </summary>
353        public List<string> MountPoints
354        {
355            get { return mountPoints; }
356            set { mountPoints = value; }
357        }
358        private List<string> mountPoints = new List<string>();
359
360        /// <summary>
361        /// Gets whether the current volume is mounted at any place.
362        /// </summary>
363        public bool IsMounted
364        {
365            get { return mountPoints.Count != 0; }
366        }
367
368        #region Windows API Functions
369        internal const int MaxPath = 260;
370        internal const int LongPath = 32768;
371
372        /// <summary>
373        /// Retrieves information about the file system and volume associated with
374        /// the specified root directory.
375        ///
376        /// To specify a handle when retrieving this information, use the
377        /// GetVolumeInformationByHandleW function.
378        ///
379        /// To retrieve the current compression state of a file or directory, use
380        /// FSCTL_GET_COMPRESSION.
381        /// </summary>
382        /// <param name="lpRootPathName">    A pointer to a string that contains
383        /// the root directory of the volume to be described.
384        ///
385        /// If this parameter is NULL, the root of the current directory is used.
386        /// A trailing backslash is required. For example, you specify
387        /// \\MyServer\MyShare as "\\MyServer\MyShare\", or the C drive as "C:\".</param>
388        /// <param name="lpVolumeNameBuffer">A pointer to a buffer that receives
389        /// the name of a specified volume. The maximum buffer size is MAX_PATH+1.</param>
390        /// <param name="nVolumeNameSize">The length of a volume name buffer, in
391        /// TCHARs. The maximum buffer size is MAX_PATH+1.
392        ///
393        /// This parameter is ignored if the volume name buffer is not supplied.</param>
394        /// <param name="lpVolumeSerialNumber">A pointer to a variable that receives
395        /// the volume serial number.
396        ///
397        /// This parameter can be NULL if the serial number is not required.
398        ///
399        /// This function returns the volume serial number that the operating system
400        /// assigns when a hard disk is formatted. To programmatically obtain the
401        /// hard disk's serial number that the manufacturer assigns, use the
402        /// Windows Management Instrumentation (WMI) Win32_PhysicalMedia property
403        /// SerialNumber.</param>
404        /// <param name="lpMaximumComponentLength">A pointer to a variable that
405        /// receives the maximum length, in TCHARs, of a file name component that
406        /// a specified file system supports.
407        ///
408        /// A file name component is the portion of a file name between backslashes.
409        ///
410        /// The value that is stored in the variable that *lpMaximumComponentLength
411        /// points to is used to indicate that a specified file system supports
412        /// long names. For example, for a FAT file system that supports long names,
413        /// the function stores the value 255, rather than the previous 8.3 indicator.
414        /// Long names can also be supported on systems that use the NTFS file system.</param>
415        /// <param name="lpFileSystemFlags">A pointer to a variable that receives
416        /// flags associated with the specified file system.
417        ///
418        /// This parameter can be one or more of the FS_FILE* flags. However,
419        /// FS_FILE_COMPRESSION and FS_VOL_IS_COMPRESSED are mutually exclusive.</param>
420        /// <param name="lpFileSystemNameBuffer">A pointer to a buffer that receives
421        /// the name of the file system, for example, the FAT file system or the
422        /// NTFS file system. The maximum buffer size is MAX_PATH+1.</param>
423        /// <param name="nFileSystemNameSize">The length of the file system name
424        /// buffer, in TCHARs. The maximum buffer size is MAX_PATH+1.
425        ///
426        /// This parameter is ignored if the file system name buffer is not supplied.</param>
427        /// <returns>If all the requested information is retrieved, the return value
428        /// is nonzero.
429        ///
430        ///
431        /// If not all the requested information is retrieved, the return value is
432        /// zero (0). To get extended error information, call GetLastError.</returns>
433        [DllImport("Kernel32.dll", SetLastError = true, EntryPoint = "GetVolumeInformationW")]
434        [return: MarshalAs(UnmanagedType.Bool)]
435        internal static extern bool GetVolumeInformation(
436            [MarshalAs(UnmanagedType.LPWStr)] string lpRootPathName,
437            IntPtr lpVolumeNameBuffer,
438            uint nVolumeNameSize,
439            out uint lpVolumeSerialNumber,
440            out uint lpMaximumComponentLength,
441            out uint lpFileSystemFlags,
442            IntPtr lpFileSystemNameBuffer,
443            uint nFileSystemNameSize);
444
445        /// <summary>
446        /// Retrieves information about the specified disk, including the amount
447        /// of free space on the disk.
448        ///
449        /// The GetDiskFreeSpace function cannot report volume sizes that are
450        /// greater than 2 gigabytes (GB). To ensure that your application works
451        /// with large capacity hard drives, use the GetDiskFreeSpaceEx function.
452        /// </summary>
453        /// <param name="lpRootPathName">The root directory of the disk for which
454        /// information is to be returned. If this parameter is NULL, the function
455        /// uses the root of the current disk. If this parameter is a UNC name,
456        /// it must include a trailing backslash (for example, \\MyServer\MyShare\).
457        /// Furthermore, a drive specification must have a trailing backslash
458        /// (for example, C:\). The calling application must have FILE_LIST_DIRECTORY
459        /// access rights for this directory.</param>
460        /// <param name="lpSectorsPerCluster">A pointer to a variable that receives
461        /// the number of sectors per cluster.</param>
462        /// <param name="lpBytesPerSector">A pointer to a variable that receives
463        /// the number of bytes per sector.</param>
464        /// <param name="lpNumberOfFreeClusters">A pointer to a variable that
465        /// receives the total number of free clusters on the disk that are
466        /// available to the user who is associated with the calling thread.
467        ///
468        /// If per-user disk quotas are in use, this value may be less than the
469        /// total number of free clusters on the disk.</param>
470        /// <param name="lpTotalNumberOfClusters">A pointer to a variable that
471        /// receives the total number of clusters on the disk that are available
472        /// to the user who is associated with the calling thread.
473        ///
474        /// If per-user disk quotas are in use, this value may be less than the
475        /// total number of clusters on the disk.</param>
476        /// <returns>If the function succeeds, the return value is true. To get
477        /// extended error information, call Marshal.GetLastWin32Error().</returns>
478        [DllImport("Kernel32.dll", SetLastError = true, EntryPoint = "GetDiskFreeSpaceW")]
479        [return: MarshalAs(UnmanagedType.Bool)]
480        internal static extern bool GetDiskFreeSpace(
481            [MarshalAs(UnmanagedType.LPWStr)] string lpRootPathName,
482            out UInt32 lpSectorsPerCluster, out UInt32 lpBytesPerSector,
483            out UInt32 lpNumberOfFreeClusters, out UInt32 lpTotalNumberOfClusters);
484
485        /// <summary>
486        /// Retrieves information about the amount of space that is available on
487        /// a disk volume, which is the total amount of space, the total amount
488        /// of free space, and the total amount of free space available to the
489        /// user that is associated with the calling thread.
490        /// </summary>
491        /// <param name="lpDirectoryName">A directory on the disk.
492        ///
493        /// If this parameter is NULL, the function uses the root of the current
494        /// disk.
495        ///
496        /// If this parameter is a UNC name, it must include a trailing backslash,
497        /// for example, "\\MyServer\MyShare\".
498        ///
499        /// This parameter does not have to specify the root directory on a disk.
500        /// The function accepts any directory on a disk.
501        ///
502        /// The calling application must have FILE_LIST_DIRECTORY access rights
503        /// for this directory.</param>
504        /// <param name="lpFreeBytesAvailable">A pointer to a variable that receives
505        /// the total number of free bytes on a disk that are available to the
506        /// user who is associated with the calling thread.
507        ///
508        /// This parameter can be NULL.
509        ///
510        /// If per-user quotas are being used, this value may be less than the
511        /// total number of free bytes on a disk.</param>
512        /// <param name="lpTotalNumberOfBytes">A pointer to a variable that receives
513        /// the total number of bytes on a disk that are available to the user who
514        /// is associated with the calling thread.
515        ///
516        /// This parameter can be NULL.
517        ///
518        /// If per-user quotas are being used, this value may be less than the
519        /// total number of bytes on a disk.
520        ///
521        /// To determine the total number of bytes on a disk or volume, use
522        /// IOCTL_DISK_GET_LENGTH_INFO.</param>
523        /// <param name="lpTotalNumberOfFreeBytes">A pointer to a variable that
524        /// receives the total number of free bytes on a disk.
525        ///
526        /// This parameter can be NULL.</param>
527        /// <returns>If the function succeeds, the return value is nonzero.
528        ///
529        /// If the function fails, the return value is zero (0). To get extended
530        /// error information, call GetLastError.</returns>
531        [DllImport("Kernel32.dll", SetLastError = true, EntryPoint = "GetDiskFreeSpaceExW")]
532        [return: MarshalAs(UnmanagedType.Bool)]
533        internal static extern bool GetDiskFreeSpaceEx(
534            [MarshalAs(UnmanagedType.LPWStr)] string lpDirectoryName,
535            out UInt64 lpFreeBytesAvailable,
536            out UInt64 lpTotalNumberOfBytes,
537            out UInt64 lpTotalNumberOfFreeBytes);
538
539        /// <summary>
540        /// Retrieves the name of a volume on a computer. FindFirstVolume is used
541        /// to begin scanning the volumes of a computer.
542        /// </summary>
543        /// <param name="lpszVolumeName">A pointer to a buffer that receives a
544        /// null-terminated string that specifies the unique volume name of the
545        /// first volume found.</param>
546        /// <param name="cchBufferLength">The length of the buffer to receive the
547        /// name, in TCHARs.</param>
548        /// <returns>If the function succeeds, the return value is a search handle
549        /// used in a subsequent call to the FindNextVolume and FindVolumeClose
550        /// functions.
551        ///
552        /// If the function fails to find any volumes, the return value is the
553        /// INVALID_HANDLE_VALUE error code. To get extended error information,
554        /// call GetLastError.</returns>
555        [DllImport("Kernel32.dll", SetLastError = true, EntryPoint = "FindFirstVolumeW")]
556        internal static extern SafeFileHandle FindFirstVolume(
557            IntPtr lpszVolumeName,
558            uint cchBufferLength);
559
560        /// <summary>
561        /// Continues a volume search started by a call to the FindFirstVolume
562        /// function. FindNextVolume finds one volume per call.
563        /// </summary>
564        /// <param name="hFindVolume">The volume search handle returned by a previous
565        /// call to the FindFirstVolume function.</param>
566        /// <param name="lpszVolumeName">A pointer to a string that receives the
567        /// unique volume name found.</param>
568        /// <param name="cchBufferLength">The length of the buffer that receives
569        /// the name, in TCHARs.</param>
570        /// <returns>If the function succeeds, the return value is nonzero.
571        ///
572        /// If the function fails, the return value is zero. To get extended error
573        /// information, call GetLastError. If no matching files can be found, the
574        /// GetLastError function returns the ERROR_NO_MORE_FILES error code. In
575        /// that case, close the search with the FindVolumeClose function.</returns>
576        [DllImport("Kernel32.dll", SetLastError = true, EntryPoint = "FindNextVolumeW")]
577        [return: MarshalAs(UnmanagedType.Bool)]
578        internal static extern bool FindNextVolume(SafeHandle hFindVolume,
579            IntPtr lpszVolumeName, uint cchBufferLength);
580
581        /// <summary>
582        /// Closes the specified volume search handle. The FindFirstVolume and
583        /// FindNextVolume functions use this search handle to locate volumes.
584        /// </summary>
585        /// <param name="hFindVolume">The volume search handle to be closed. This
586        /// handle must have been previously opened by the FindFirstVolume function.</param>
587        /// <returns>If the function succeeds, the return value is nonzero.
588        ///
589        /// If the function fails, the return value is zero. To get extended error
590        /// information, call GetLastError.</returns>
591        [DllImport("Kernel32.dll", SetLastError = true)]
592        [return: MarshalAs(UnmanagedType.Bool)]
593        internal static extern bool FindVolumeClose(SafeHandle hFindVolume);
594
595        /// <summary>
596        /// Retrieves the name of a volume mount point on the specified volume.
597        /// FindFirstVolumeMountPoint is used to begin scanning the volume mount
598        /// points on a volume.
599        /// </summary>
600        /// <param name="lpszRootPathName">The unique volume name of the volume
601        /// to scan for volume mount points. A trailing backslash is required.</param>
602        /// <param name="lpszVolumeMountPoint">A pointer to a buffer that receives
603        /// the name of the first volume mount point found.</param>
604        /// <param name="cchBufferLength">The length of the buffer that receives
605        /// the volume mount point name, in TCHARs.</param>
606        /// <returns>If the function succeeds, the return value is a search handle
607        /// used in a subsequent call to the FindNextVolumeMountPoint and
608        /// FindVolumeMountPointClose functions.
609        ///
610        /// If the function fails to find a volume mount point on the volume, the
611        /// return value is the INVALID_HANDLE_VALUE error code. To get extended
612        /// error information, call GetLastError.</returns>
613        [DllImport("Kernel32.dll", SetLastError = true, EntryPoint = "FindFirstVolumeMountPointW")]
614        internal static extern SafeFileHandle FindFirstVolumeMountPoint(
615            [MarshalAs(UnmanagedType.LPWStr)] string lpszRootPathName,
616            IntPtr lpszVolumeMountPoint,
617            uint cchBufferLength);
618
619        /// <summary>
620        /// Continues a volume mount point search started by a call to the
621        /// FindFirstVolumeMountPoint function. FindNextVolumeMountPoint finds one
622        /// volume mount point per call.
623        /// </summary>
624        /// <param name="hFindVolumeMountPoint">A mount-point search handle returned
625        /// by a previous call to the FindFirstVolumeMountPoint function.</param>
626        /// <param name="lpszVolumeMountPoint">A pointer to a buffer that receives
627        /// the name of the volume mount point found.</param>
628        /// <param name="cchBufferLength">The length of the buffer that receives
629        /// the names, in TCHARs.</param>
630        /// <returns>If the function succeeds, the return value is nonzero.
631        ///
632        /// If the function fails, the return value is zero. To get extended error
633        /// information, call GetLastError. If no matching files can be found, the
634        /// GetLastError function returns the ERROR_NO_MORE_FILES error code. In
635        /// that case, close the search with the FindVolumeMountPointClose function.</returns>
636        [DllImport("Kernel32.dll", SetLastError = true, EntryPoint = "FindNextVolumeMountPointW")]
637        [return: MarshalAs(UnmanagedType.Bool)]
638        internal static extern bool FindNextVolumeMountPoint(SafeHandle hFindVolumeMountPoint,
639            IntPtr lpszVolumeMountPoint,
640            uint cchBufferLength);
641
642        /// <summary>
643        /// Closes the specified mount-point search handle. The FindFirstVolumeMountPoint
644        /// and FindNextVolumeMountPoint  functions use this search handle to locate
645        /// volume mount points on a specified volume.
646        /// </summary>
647        /// <param name="hFindVolumeMountPoint">The mount-point search handle to
648        /// be closed. This handle must have been previously opened by the
649        /// FindFirstVolumeMountPoint function.</param>
650        /// <returns>If the function succeeds, the return value is nonzero.
651        ///
652        /// If the function fails, the return value is zero. To get extended error
653        /// information, call GetLastError.</returns>
654        [DllImport("Kernel32.dll", SetLastError = true)]
655        [return: MarshalAs(UnmanagedType.Bool)]
656        internal static extern bool FindVolumeMountPointClose(SafeHandle hFindVolumeMountPoint);
657
658        /// <summary>
659        /// Retrieves the unique volume name for the specified volume mount point or root directory.
660        /// </summary>
661        /// <param name="lpszVolumeMountPoint">The path of a volume mount point (with a trailing
662        /// backslash, "\") or a drive letter indicating a root directory (in the
663        /// form "D:\").</param>
664        /// <param name="lpszVolumeName">A pointer to a string that receives the
665        /// volume name. This name is a unique volume name of the form
666        /// "\\?\Volume{GUID}\" where GUID is the GUID that identifies the volume.</param>
667        /// <param name="cchBufferLength">The length of the output buffer, in TCHARs.
668        /// A reasonable size for the buffer to accommodate the largest possible
669        /// volume name is 50 characters.</param>
670        /// <returns>If the function succeeds, the return value is nonzero.
671        ///
672        /// If the function fails, the return value is zero. To get extended
673        /// error information, call GetLastError.</returns>
674        [DllImport("Kernel32.dll", SetLastError = true, EntryPoint = "GetVolumeNameForVolumeMountPointW")]
675        [return: MarshalAs(UnmanagedType.Bool)]
676        internal static extern bool GetVolumeNameForVolumeMountPoint(
677            [MarshalAs(UnmanagedType.LPWStr)] string lpszVolumeMountPoint,
678            IntPtr lpszVolumeName,
679            uint cchBufferLength);
680
681        /// <summary>
682        /// Retrieves a list of path names for the specified volume name.
683        /// </summary>
684        /// <param name="lpszVolumeName">The volume name.</param>
685        /// <param name="lpszVolumePathNames">A pointer to a buffer that receives
686        /// the list of volume path names. The list is an array of null-terminated
687        /// strings terminated by an additional NULL character. If the buffer is
688        /// not large enough to hold the complete list, the buffer holds as much
689        /// of the list as possible.</param>
690        /// <param name="cchBufferLength">The length of the lpszVolumePathNames
691        /// buffer, in TCHARs.</param>
692        /// <param name="lpcchReturnLength">If the call is successful, this parameter
693        /// is the number of TCHARs copied to the lpszVolumePathNames buffer. Otherwise,
694        /// this parameter is the size of the buffer required to hold the complete
695        /// list, in TCHARs.</param>
696        /// <returns></returns>
697        [DllImport("Kernel32.dll", SetLastError = true, EntryPoint = "GetVolumePathNamesForVolumeNameW")]
698        internal static extern bool GetVolumePathNamesForVolumeName(
699            [MarshalAs(UnmanagedType.LPWStr)] string lpszVolumeName,
700            IntPtr lpszVolumePathNames,
701            uint cchBufferLength,
702            out uint lpcchReturnLength);
703
704        /// <summary>
705        /// Determines whether a disk drive is a removable, fixed, CD-ROM, RAM disk,
706        /// or network drive.
707        /// </summary>
708        /// <param name="lpRootPathName">The root directory for the drive.
709        ///
710        /// A trailing backslash is required. If this parameter is NULL, the function
711        /// uses the root of the current directory.</param>
712        /// <returns>The return value specifies the type of drive, which can be
713        /// one of the DriveInfo.DriveType values.</returns>
714        [DllImport("Kernel32.dll", SetLastError = true, EntryPoint = "GetDriveTypeW")]
715        internal static extern uint GetDriveType(
716            [MarshalAs(UnmanagedType.LPWStr)] string lpRootPathName);
717        #endregion
718    }
719}
Note: See TracBrowser for help on using the repository browser.