source: branches/eraser6/Util/VolumeInfo.cs @ 489

Revision 489, 27.7 KB checked in by lowjoel, 5 years ago (diff)

-In FAT32, the driver doesn't know FSCTL_GET_COMPRESSION so it'll just return zero.
-In FAT32, finding the volume from the mountpoint may fail with a GetLastError? value of 1

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