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

Revision 408, 27.4 KB checked in by lowjoel, 6 years ago (diff)

Silly me. I could have just used StringBuilders? for those functions parameters where strings are passed out through a buffer.

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