Platform SDK: Files and I/O

Enumerating Mount Points

The following sample demonstrates how to enumerate volumes and mount points on a computer.

This sample uses the following functions: DeleteVolumeMountPoint, FindFirstVolume, FindFirstVolumeMountPoint, FindNextVolume, FindNextVolumeMountPoint, FindVolumeClose, FindVolumeMountPointClose, GetVolumeInformation, and GetVolumeNameForVolumeMountPoint.

#define _WIN32_WINNT 0x0500

#include <windows.h>
#include <stdio.h>


#define BUFSIZE 1024            // ample space for our string buffer
#define FILESYSNAMEBUFSIZE 1024 // probably more than we need


// Process each mount point found here. This makes maintenance easier 
// than doing it in line. The result indicates whether there is 
// another mount point to be scanned.

// This routine prints out the path to a mount point and its target. 

BOOL ProcessVolumeMountPoint (HANDLE hPt,
                              char *PtBuf, DWORD dwPtBufSize,
                              char *Buf, DWORD dwBufSize)
{
   BOOL bFlag;                   // Boolean result
   char Path[BUFSIZE];           // construct a complete path here
   HANDLE hFf, hFile;            // file search, file handles
   WIN32_FIND_DATA fd;           // find data for a file search
   DWORD BytesReturned;          // from DeviceIoControl call
   char Target[BUFSIZE];         // target of mount at mount point

   printf ("\tVolume mount point found is \"%s\"\n", PtBuf);

   // Detect the volume mounted there. Unfortunately, there is no 
   // simple way to map a unique volume name to a DOS drive letter. 
   // One way to do that is to build an associative array, which we 
   // will "leave as an exercise for the student." 

   // Build a unique path to the mount point

   strcpy (Path, Buf);           
   strcat (Path, PtBuf);

   bFlag = GetVolumeNameForVolumeMountPoint(
                Path, // input volume mount point or directory
              Target, // output volume name buffer
              BUFSIZE // size of volume name buffer
           );

   if (!bFlag) 
      printf ("\tAttempt to get Volume Name for %s failed.\n", Path);
   else 
      printf ("\tTarget of the volume mount point is %s.\n", Target);
  
   // Now, either get the next mount point and return it, or return a 
   // value indicating there are no more mount points.

   bFlag = FindNextVolumeMountPoint(
                     hPt, // handle to scan
                   PtBuf, // pointer to output string
              dwPtBufSize // size of output buffer
           );

  return (bFlag);
}

// Process each volume. This makes maintenance easier than doing it
// in line. The Boolean result indicates whether there is another 
// volume to be scanned. 

BOOL ProcessVolume (HANDLE hVol, char *Buf, int iBufSize)
{
   BOOL bFlag;                  // generic results flag for return
   HANDLE hPt;                  // handle for mount point scan
   char PtBuf[BUFSIZE];         // string buffer for mount points
   DWORD dwSysFlags;            // flags that describe the file system
   char FileSysNameBuf[FILESYSNAMEBUFSIZE];

   printf ("Volume found is \"%s\".\n", Buf);

   // Is this volume NTFS? 
  GetVolumeInformation( Buf, NULL, 0, NULL, NULL,
                        &dwSysFlags, FileSysNameBuf, 
                        FILESYSNAMEBUFSIZE);

   // Detect support for reparse points, and therefore for volume 
   // mount points, which are implemented using reparse points. 

   if (! (dwSysFlags & FILE_SUPPORTS_REPARSE_POINTS)) 
   {
      printf ("\tThis file system does not support Volume Mount Points.\n");
   } 
   else 
   {
      // Start processing mount points on this volume. 

      hPt = FindFirstVolumeMountPoint(
                  Buf, // root path of volume to be scanned
                PtBuf, // pointer to output string
               BUFSIZE // size of output buffer
            );

      // Shall we error out?

      if (hPt == INVALID_HANDLE_VALUE)
      {
         printf ("\tNo volume mount points found!\n");
      } 
      else 
      {
         // Process the volume mount point.
         bFlag = ProcessVolumeMountPoint (hPt, PtBuf, BUFSIZE, Buf, BUFSIZE);

         // Do while we have volume mount points to process.
         while (bFlag) 
            bFlag = ProcessVolumeMountPoint (hPt, PtBuf, BUFSIZE, Buf, BUFSIZE);

         FindVolumeMountPointClose(hPt);
       }
   }

  // Stop processing mount points on this volume. 

   bFlag = FindNextVolume(
                hVol, // handle to scan being conducted
                 Buf, // pointer to output
             iBufSize // size of output buffer
           );

   return (bFlag); 
}

int
main(int argc, char *argv[])
{
   char buf[BUFSIZE];            // buffer for unique volume identifiers
   HANDLE hVol;                  // handle for the volume scan
   BOOL bFlag;                   // generic results flag

   // Open a scan for volumes.
   hVol = FindFirstVolume (buf, BUFSIZE );

   // Shall we error out?
   if (hVol == INVALID_HANDLE_VALUE)
   {
      printf ("No volumes found!\n");
      return (-1);
   }

   // We have a volume; process it.
   bFlag = ProcessVolume (hVol, buf, BUFSIZE);

   // Do while we have volumes to process.
   while (bFlag) 
   {
      bFlag = ProcessVolume (hVol, buf, BUFSIZE);
   }

   // Close out our volume scan.
   bFlag = FindVolumeClose(
              hVol  // handle to be closed
           );

   return (bFlag);
}