My Training Period: cc hours. Before you begin, read some instruction here.
The programming abilities for this session:
Windows Volume Management Functions
|
The following program example uses GetDriveType() to test all the drive type of the machine. The list of the drives is supplied in the program.
#include <windows.h>
#include <stdio.h>
// using two dimensional arrays to store the drive strings
char drive2[13][5] = {"A:\\", "B:\\", "C:\\", "D:\\", "E:\\", "F:\\", "G:\\", "H:\\","I:\\", "J:\\", "K:\\", "L:\\"};
int main()
{
for(int i=0; i<12; i++)
{
UINT test = GetDriveType(drive2[i]);
switch(test)
{
case 0: printf("Drive %s is type %d - Cannot be determined.\n", &drive2[i], test);
break;
case 1: printf("Drive %s is type %d - Invalid root path/Not available.\n", &drive2[i], test);
break;
case 2: printf("Drive %s is type %d - Removable.\n", &drive2[i], test);
break;
case 3: printf("Drive %s is type %d - Fixed.\n", &drive2[i], test);
break;
case 4: printf("Drive %s is type %d - Network.\n", &drive2[i], test);
break;
case 5: printf("Drive %s is type %d - CD-ROM.\n", &drive2[i], test);
break;
case 6: printf("Drive %s is type %d - RAMDISK.\n", &drive2[i], test);
break;
default : "Unknown value!\n";
}
}
return 0;
}
The output:
Drive A:\ is type 2 - Removable.
Drive B:\ is type 1 - Invalid root path/Not available.
Drive C:\ is type 3 - Fixed.
Drive D:\ is type 3 - Fixed.
Drive E:\ is type 3 - Fixed.
Drive F:\ is type 3 - Fixed.
Drive G:\ is type 3 - Fixed.
Drive H:\ is type 3 - Fixed.
Drive I:\ is type 3 - Fixed.
Drive J:\ is type 5 - CD-ROM.
Drive K:\ is type 5 - CD-ROM.
Drive L:\ is type 2 - Removable.
Press any key to continue
The following is an output sample run using VC++ EE 2005 on another machine.
The following Table lists the needed information in order to use the GetLogicalDrives() function.
The return value is a bitmask representing the currently available disk drives. Bit position 0 (the least-significant bit) is drive A, bit position 1 is drive B, bit position 2 is drive C, and so on.
Information | Description |
The function | GetLogicalDrives(). |
The use | Retrieves a bitmask representing the currently available disk drives. |
The prototype | DWORD GetLogicalDrives(void); |
Example | TCHAR szDrive[ ] = _T(" A:");
DWORD uDriveMask = GetLogicalDrives(); printf("This machine has the following logical drives:\n");
while(uDriveMask) { if(uDriveMask & 1) printf(szDrive); // binary 1 shows that the drive is available and 0 otherwise ++szDrive[1]; // shift right uDriveMask >>= 1; } |
The parameters | This function has no parameters. |
The return value | If the function succeeds, the return value is a bitmask representing the currently available disk drives. Bit position 0 (the least-significant bit) is drive A, bit position 1 is drive B, bit position 2 is drive C, and so on. |
The header file | <windows.h> |
Table 2: GetLogicalDrives() information. |
The following program example uses GetLogicalDrives() to retrieve the bitmask, then using a while loop, bitwise AND and binary shift right operator to list all the available logical drives.
#include <windows.h>
#include <direct.h>
#include <stdio.h>
#include <tchar.h>
// initial value
TCHAR szDrive[ ] = _T(" A:");
int main()
{
DWORD uDriveMask = GetLogicalDrives();
printf("The bitmask of the logical drives in hex: %0X\n", uDriveMask);
printf("The bitmask of the logical drives in decimal: %d\n", uDriveMask);
if(uDriveMask == 0)
printf("GetLogicalDrives() failed with failure code: %d\n", GetLastError());
else
{
printf("This machine has the following logical drives:\n");
while(uDriveMask)
{// use the bitwise AND, 1–available, 0-not available
if(uDriveMask & 1)
printf(szDrive);
// increment...
++szDrive[1];
// shift the bitmask binary right
uDriveMask >>= 1;
}
printf("\n ");
}
return 0;
}
The output:
The bitmask of the logical drives in hex: FFD
The bitmask of the logical drives in decimal: 4093
This machine has the following logical drives:
A: C: D: E: F: G: H: I: J: K: L:
Press any key to continue
The following is output when running using VC++ EE 2005 on another machine.
Notice that, in binary the FFD (hex) is equal to 111111111101 that is A: until L: drive with no B: drive.
The following Table lists the needed information in order to use the GetLogicalDriveStrings() function.
Information | Description |
The function | GetLogicalDriveStrings(). |
The use | Fills a buffer with strings that specify valid drives in the system. |
The prototype | DWORD GetLogicalDriveStrings(DWORD nBufferLength, LPTSTR lpBuffer); |
Example | DWORD mydrives = 100; char lpBuffer[100];
GetLogicalDriveStrings(mydrives, lpBuffer); |
The parameters | nBufferLength - [in] Maximum size of the buffer pointed to by lpBuffer, in TCHARs. This size does not include the terminating null character. If this parameter is zero, lpBuffer is not used. lpBuffer - [out] Pointer to a buffer that receives a series of null-terminated strings, one for each valid drive in the system, plus with an additional null character. Each string is a device name. |
The return value | If the function succeeds, the return value is the length, in characters, of the strings copied to the buffer, not including the terminating null character. Note that an ANSI-ASCII null character uses one byte, but a Unicode null character uses two bytes. If the buffer is not large enough, the return value is greater than nBufferLength. It is the size of the buffer required to hold the drive strings. If the function fails, the return value is zero. To get extended error information, use the GetLastError() function. |
The header file | <windows.h> |
Table 3: GetLogicalDriveStrings() information. |
The following program example uses GetLogicalDriveStrings() to list all the available logical drives.
#include <windows.h>
#include <stdio.h>
// buffer length
DWORD mydrives = 100;
// buffer for drive string storage
char lpBuffer[100];
int main()
{
DWORD test = GetLogicalDriveStrings( mydrives, lpBuffer);
printf("GetLogicalDriveStrings() return value: %d\nError: %d \n", test, GetLastError());
printf("The logical drives of this machine are:\n");
for(int i = 0; i<100; i++)
printf("%c", lpBuffer[i]);
printf("\n");
return 0;
}
The output:
GetLogicalDriveStrings() return value: 44
Error: 0
The logical drives of this machine are:
A:\ C:\ D:\ E:\ F:\ G:\ H:\ I:\ J:\ K:\ L:\
Press any key to continue
VC++ EE 2005 sample output.
The following Table lists the needed information in order to use the QueryDosDevice() function and then followed by a program example.
Information | Description |
The function | QueryDosDevice(). |
The use | Retrieves information about MS-DOS device names. The function can obtain the current mapping for a particular MS-DOS device name. The function can also obtain a list of all existing MS-DOS device names. |
The prototype | DWORD QueryDosDevice( LPCTSTR lpDeviceName, LPTSTR lpTargetPath, DWORD ucchMax ); |
Example | char lpDeviceName[11][3] = {"A:", "C:", "D:", "E:", "F:", "G:", "H:","I:", "J:", "K:", "L:"}; // the buffer for storage char lpTargetPath[1000];
QueryDosDevice(lpDeviceName[i], lpTargetPath, 1000); |
The parameters | lpDeviceName - [in] Pointer to an MS-DOS device name string specifying the target of the query. The device name cannot have a trailing backslash. This parameter can be NULL. In that case, the QueryDosDevice() function will store a list of all existing MS-DOS device names into the buffer pointed to by lpTargetPath. lpTargetPath - [out] Pointer to a buffer that will receive the result of the query. The function fills this buffer with one or more null-terminated strings. The final null-terminated string is followed by an additional NULL. If lpDeviceName is non-NULL, the function retrieves information about the particular MS-DOS device specified by lpDeviceName. The first null-terminated string stored into the buffer is the current mapping for the device. The other null-terminated strings represent undeleted prior mappings for the device. If lpDeviceName is NULL, the function retrieves a list of all existing MS-DOS device names. Each null-terminated string stored into the buffer is the name of an existing MS-DOS device. ucchMax - [in] Maximum number of TCHARs that can be stored into the buffer pointed to by lpTargetPath. |
The return value | If the function succeeds, the return value is the number of TCHARs stored into the buffer pointed to by lpTargetPath. If the function fails, the return value is zero. To get extended error information, call GetLastError(). If the buffer is too small, the function fails and the last error code is ERROR_INSUFFICIENT_BUFFER. |
The header file | <windows.h> |
Table 4: QueryDosDevice() information. |
The QueryDosDevice() function retrieves information about MS-DOS device names. The function can obtain the current mapping for a particular MS-DOS device name. The function can also obtain a list of all existing MS-DOS device names.
MS-DOS device names are stored as junctions in the object name space. The code that converts an MS-DOS path into a corresponding path uses these junctions to map MS-DOS devices and drive letters.
The QueryDosDevice() function enables an application to query the names of the junctions used to implement the MS-DOS device namespace as well as the value of each specific junction.
When all existing MS-DOS device names are queried, the list of device names that are returned is dependent on whether it is running in the LocalSystem context.
If so, only the device names included in the Global MS-DOS Device namespace will be returned.
If not, a concatenation of the device names in the Global and Local MS-DOS Device namespaces will be returned. If a device name exists in both namespaces, QueryDosDevice() will return the entry in the Local MS-DOS Device namespace.
Program example using QueryDosDevice().
#include <windows.h>
#include <stdio.h>
// query these on my machine. The L: is thumb drive, J: and K: are CD-ROMs
char lpDeviceName[11][3] = {"A:", "C:", "D:", "E:", "F:", "G:", "H:","I:", "J:", "K:", "L:"};
// the buffer for storage
char lpTargetPath[1000];
int main()
{
for(int i=0; i<13; i++)
{
// using NULL for the parameter 1 is not working lol...
DWORD test = QueryDosDevice(lpDeviceName[i], lpTargetPath, 1000);
// test the return value and error if any
printf("\nQueryDosDevice() return value: %d, Error: %d\n", test, GetLastError());
printf("The DOS device for %s is:\n", lpDeviceName[i]);
// display the result
for(int i = 0; i<35; i++)
printf("%c", lpTargetPath[i]);
}
printf("\n");
return 0;
}
The output:
QueryDosDevice() return value: 17, Error: 0
The DOS device for A: is:
\Device\Floppy0
QueryDosDevice() return value: 25, Error: 0
The DOS device for C: is:
\Device\HarddiskVolume1
QueryDosDevice() return value: 25, Error: 0
The DOS device for D: is:
\Device\HarddiskVolume5
QueryDosDevice() return value: 25, Error: 0
The DOS device for E: is:
\Device\HarddiskVolume2
QueryDosDevice() return value: 25, Error: 0
The DOS device for F: is:
\Device\HarddiskVolume3
QueryDosDevice() return value: 25, Error: 0
The DOS device for G: is:
\Device\HarddiskVolume4
QueryDosDevice() return value: 25, Error: 0
The DOS device for H: is:
\Device\HarddiskVolume6
QueryDosDevice() return value: 25, Error: 0
The DOS device for I: is:
\Device\HarddiskVolume7
QueryDosDevice() return value: 16, Error: 0
The DOS device for J: is:
\Device\CdRom0 olume7
QueryDosDevice() return value: 16, Error: 0
The DOS device for K: is:
\Device\CdRom1 olume7
QueryDosDevice() return value: 30, Error: 0
The DOS device for L: is:
\Device\Harddisk2\DP(1)0-0+a
QueryDosDevice() return value: 0, Error: 6
The DOS device for is:
\Device\Harddisk2\DP(1)0-0+a
QueryDosDevice() return value: 0, Error: 6
The DOS device for is:
\Device\Harddisk2\DP(1)0-0+a
Press any key to continue
A VC++ EE 2005 sample output.
![]() |
The following Table lists the needed information in order to use the GetDiskFreeSpaceEx() function.
Information | Description |
The function | GetDiskFreeSpaceEx(). |
The use | Retrieves information about the amount of space available on a disk volume: the total amount of space, the total amount of free space, and the total amount of free space available to the user associated with the calling thread. |
The prototype | BOOL GetDiskFreeSpaceEx( LPCTSTR lpDirectoryName, PULARGE_INTEGER lpFreeBytesAvailable, PULARGE_INTEGER lpTotalNumberOfBytes, PULARGE_INTEGER lpTotalNumberOfFreeBytes); |
Example | char pszDrive[10] = "C:\\"; DWORD dwSectPerClust, dwBytesPerSect, dwFreeClusters, dwTotalClusters;
GetDiskFreeSpace(pszDrive, &dwSectPerClust, &dwBytesPerSect, &dwFreeClusters, &dwTotalClusters); |
The parameters | lpDirectoryName - [in] Pointer to a null-terminated string that specifies a directory on the disk of interest. If this parameter is NULL, the function uses the root of the current disk. If this parameter is a UNC name, it must include a trailing backslash (for example, \\MyServer\MyShare\). Note that this parameter does not have to specify the root directory on a disk. The function accepts any directory on the disk. lpFreeBytesAvailable - [out] Pointer to a variable that receives the total number of free bytes on the disk that are available to the user associated with the calling thread. This parameter can be NULL. If per-user quotas are in use, this value may be less than the total number of free bytes on the disk. lpTotalNumberOfBytes - [out] Pointer to a variable that receives the total number of bytes on the disk that are available to the user associated with the calling thread. This parameter can be NULL. If per-user quotas are in use, this value may be less than the total number of bytes on the disk. To determine the total number of bytes on a disk or volume, use IOCTL_DISK_GET_LENGTH_INFO. lpTotalNumberOfFreeBytes - [out] Pointer to a variable that receives the total number of free bytes on the disk. This parameter can be NULL. |
The return value | If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error information, call GetLastError(). |
The header file | <windows.h> |
Table 5: GetDiskFreeSpaceEx() information. |
The GetDiskFreeSpace() function retrieves information about the specified disk, including the amount of free space on the disk.
The GetDiskFreeSpace() function cannot report volume sizes that are greater than 2 gigabytes (GB) but when tested it just OK for volume size greater than 2GB!
For large capacity hard drives, use the GetDiskFreeSpaceEx() function.
Program example using GetDiskFreeSpaceEx() and GetDiskFreeSpace() functions showing the free space of dive C.
#include <windows.h>
#include <stdio.h>
int main()
{
char pszDrive[10] = "C:\\";
// 64 bits integer
__int64 lpFreeBytesAvailable, lpTotalNumberOfBytes, lpTotalNumberOfFreeBytes;
DWORD dwSectPerClust, dwBytesPerSect, dwFreeClusters, dwTotalClusters;
BOOL test = GetDiskFreeSpaceEx(
pszDrive,
(PULARGE_INTEGER)&lpFreeBytesAvailable,
(PULARGE_INTEGER)&lpTotalNumberOfBytes,
(PULARGE_INTEGER)&lpTotalNumberOfFreeBytes
);
printf("Drive to be checked: %s\n", pszDrive);
printf("\nUsing GetDiskFreeSpaceEx()...\n");
// check the return value
printf("The return value: %d, error code: %d\n", test, GetLastError());
printf("Total number of free bytes available for user-caller: %ul\n", lpFreeBytesAvailable);
printf("Total number of bytes available for user: %ul\n", lpTotalNumberOfBytes);
// just straight to the free bytes result
printf("Total number of free bytes on disk: %ul\n", lpTotalNumberOfFreeBytes);
BOOL fResult = GetDiskFreeSpace(pszDrive,
&dwSectPerClust,
&dwBytesPerSect,
&dwFreeClusters,
&dwTotalClusters);
printf("\nUsing GetDiskFreeSpace()...\n");
printf("The return value: %d, error code: %d\n", fResult, GetLastError());
printf("Sector per cluster = %ul\n", dwSectPerClust);
printf("Bytes per sector = %ul\n", dwBytesPerSect);
printf("Free cluster = %ul\n", dwFreeClusters);
printf("Total cluster = %ul\n", dwTotalClusters);
// using GetDiskFreeSpace() need some calculation for the free bytes on disk
printf("Total free bytes = %ul\n", (dwFreeClusters*dwSectPerClust*dwBytesPerSect));
return 0;
}
The output:
Drive to be checked: C:\
Using GetDiskFreeSpaceEx()...
The return value: 1, error code: 0
Total number of free bytes available for user-caller: 263147520l
Total number of bytes available for user: 1897263104l
Total number of free bytes on disk: 263147520l
Using GetDiskFreeSpace()...
The return value: 1, error code: 0
Sector per cluster = 8l
Bytes per sector = 512l
Free cluster = 64245l
Total cluster = 2560351l
Total free bytes = 263147520l
Press any key to continue
VC++ EE 2005 sample output.
Two factors can make it hard to reliably mount a specific volume at a specified volume mount point across operating system restarts.
Two different volumes can have the same label, which makes them indistinguishable except by drive letter.
Drive letters do not necessarily remain the same. If a computer's administrator does not use the Disk Administrator to enforce drive letters, then drive letters can change as drives are removed from or added to the system.
To solve this problem, the system refers to volumes to be mounted with unique volume names. These are strings of this form:
"\\?\Volume{GUID}\"
Where GUID is a globally unique identifier (GUID) that identifies the volume. For example:
\\?\Volume{a3446ed5-ebd9-11d8-a25c-806d6172696f}\
The \\?\ prefix disables path parsing and is not parsed along with the path. For example, "\\?\C:\myworld\private" is parsed as "C:\myworld\private".
By pre-pending paths with \\?\, you can specify paths that are 32,767 Unicode characters long. However, each component in the path cannot be more than a file-system-specific value returned by the function GetVolumeInformation().
You must specify full paths when using specifying unique volume names with \\?\. This prefix can also be used with paths constructed according to the universal naming convention (UNC), such as "\\OtherComputer\Directory\Filename.ext".
All volume mount point functions that take a unique volume name as a parameter require the trailing backslash; and all volume mount point functions that return a unique volume name provide the trailing backslash.
However, this is not the case with CreateFile(). You can open a volume by calling CreateFile() and omit the trailing backslash from the volume name you specify.
CreateFile() processes a unique volume name with an appended backslash as the root directory of the volume.
The operating system assigns a unique volume name to a volume when the computer first encounters it such as during formatting or installation.
Path lengths may be a concern when a volume with a deep directory tree is mounted to another volume. This is because path of the mounted volume is concatenated to the path of the mount point.
The globally defined constant MAX_PATH defines the maximum number of characters a path can have. You can avoid this constraint by doing the following:
Refer to volumes by their unique volume names.
Use the Unicode (W) versions of file functions, which support the \\?\ prefix.
The following Table lists the needed information in order to use the GetVolumeInformation() function.
Information | Description |
The function | GetVolumeInformation(). |
The use | Retrieves information about a file system and volume whose root directory is specified. |
The prototype | BOOL GetVolumeInformation( LPCTSTR lpRootPathName, LPTSTR lpVolumeNameBuffer, DWORD nVolumeNameSize, LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength, LPDWORD lpFileSystemFlags, LPTSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize); |
Example | #define BUFSIZE MAX_PATH #define FILESYSNAMEBUFSIZE MAX_PATH
// buffer for unique volume identifiers char buf[BUFSIZE]; DWORD lpMaximumComponentLength; // flags that describe the file system DWORD dwSysFlags; char FileSysNameBuf[FILESYSNAMEBUFSIZE];
GetVolumeInformation( buf, NULL, BUFSIZE, NULL, &lpMaximumComponentLength, &dwSysFlags, FileSysNameBuf, FILESYSNAMEBUFSIZE); |
The parameters | lpRootPathName - [in] Pointer to a string that contains the root directory of the volume to be described. If this parameter is NULL, the root of the current directory is used. A trailing backslash is required. For example, you would specify \\MyServer\MyShare as \\MyServer\MyShare\, or the C drive as "C:\". lpVolumeNameBuffer - [out] Pointer to a buffer that receives the name of the specified volume. nVolumeNameSize - [in] Length of the volume name buffer, in TCHARs. This parameter is ignored if the volume name buffer is not supplied. lpVolumeSerialNumber - [out] Pointer to a variable that receives the volume serial number. This parameter can be NULL if the serial number is not required. lpMaximumComponentLength - [out] Pointer to a variable that receives the maximum length, in TCHARs, of a file name component supported by the specified file system. A file name component is that portion of a file name between backslashes. The value stored in variable pointed to by *lpMaximumComponentLength is used to indicate that long names are supported by the specified file system. For example, for a FAT file system supporting long names, the function stores the value 255, rather than the previous 8.3 indicator. Long names can also be supported on systems that use the NTFS file system. lpFileSystemFlags - [out] Pointer to a variable that receives flags associated with the specified file system. This parameter can be one or more of the following flags; however, FS_FILE_COMPRESSION and FS_VOL_IS_COMPRESSED are mutually exclusive.
lpFileSystemNameBuffer - [out] Pointer to a buffer that receives the name of the file system (such as FAT or NTFS). nFileSystemNameSize - [in] Length of the file system name buffer, in TCHARs. This parameter is ignored if the file system name buffer is not supplied. |
The return value | If all the requested information is retrieved, the return value is nonzero. If not all the requested information is retrieved, the return value is zero. To get extended error information, call GetLastError(). |
The header file | <windows.h> |
Table 6: GetVolumeInformation() information. |
If you are attempting to obtain information about a floppy drive that does not have a floppy disk or a CD-ROM drive that does not have a compact disc, the system displays a message "drive not ready" (and for GUI, displays a message box asking the user to insert a floppy disk or a compact disc, respectively).
To prevent the system from displaying this message box, call the SetErrorMode() function with SEM_FAILCRITICALERRORS.
The FS_VOL_IS_COMPRESSED flag is the only indicator of volume-based compression. The file system name is not altered to indicate compression. This flag comes back set on a DoubleSpace volume, for example.
With volume-based compression, an entire volume is either compressed or not compressed.
The FS_FILE_COMPRESSION flag indicates whether a file system supports file-based compression. With file-based compression, individual files can be compressed or not compressed.
The FS_FILE_COMPRESSION and FS_VOL_IS_COMPRESSED flags are mutually exclusive; both bits cannot come back set.
The maximum component length value, stored in lpMaximumComponentLength, is the only indicator that a volume supports longer-than-normal FAT (or other file system) file names.
The file system name is not altered to indicate support for long file names.
The FindFirstVolume() function opens a volume search handle and returns information about the first volume found on a computer. After the search handle is established, you can use the FindNextVolume() function to search for other volumes.
When the search handle is no longer needed, close it by using the FindVolumeClose() function.
You should not assume any correlation between the order of volumes returned with these functions and the order of volumes on the computer. In particular, do not assume any correlation between volume order and drive letters as assigned by the BIOS (if any) or the Disk Administrator.
The following Table lists the needed information in order to use the FindFirstVolume() function.
Information | Description |
The function | FindFirstVolume(). |
The use | Used to begin scanning the volumes of a computer. Returns the name of a volume on a computer. |
The prototype | HANDLE FindFirstVolume( LPTSTR lpszVolumeName, DWORD cchBufferLength ); |
Example | #define BUFSIZE MAX_PATH char buf[BUFSIZE]; hVol = FindFirstVolume(buf, BUFSIZE); if(hVol == INVALID_HANDLE_VALUE) { printf ("No volumes found!\n"); return (-1); } |
The parameters | lpszVolumeName - [out] Pointer to a buffer that receives a null-terminated string that specifies the unique volume name of the first volume found. cchBufferLength - [in] Length of the buffer to receive the name, in TCHARs. |
The return value | If the function succeeds, the return value is a search handle used in a subsequent call to the FindNextVolume() and FindVolumeClose() functions. If the function fails to find any volumes, the return value is the INVALID_HANDLE_VALUE error code. To get extended error information, call GetLastError(). |
The header file | <windows.h> |
Table 7: FindFirstVolume() information. |
After the search handle is established by calling FindFirstVolume(), you can use the FindNextVolume() function to search for other volumes.
The following Table lists the needed information in order to use the FindNextVolume() function.
Information | Description |
The function | FindNextVolume(). |
The use | Continues a volume search started by a call to the FindFirstVolume() function. FindNextVolume() finds one volume per call. |
The prototype | BOOL FindNextVolume( HANDLE hFindVolume, LPTSTR lpszVolumeName, DWORD cchBufferLength); |
Example | #define Bufsize MAX_PATH
HANDLE hVol; // buffer for unique volume identifiers char Buffer[Bufsize]; hVol = FindFirstVolume(Buffer, Bufsize);
FindNextVolume( hVol, // handle to search being conducted Buf, // pointer to output BufSize); // size of output buffer |
The parameters | hFindVolume - [in] Volume search handle returned by a previous call to the FindFirstVolume() function. lpszVolumeName - [out] Pointer to a string that receives the unique volume name found. cchBufferLength - [in] Length of the buffer that receives the name, in TCHARs. |
The return value | If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error information, call GetLastError(). If no matching files can be found, the GetLastError() function returns the ERROR_NO_MORE_FILES error code. In that case, close the search with the FindVolumeClose() function. |
The header file | <windows.h> |
Table 8: FindNextVolume() information. |
The Windows Xp machine used for some of the previous and the following program examples testing has the following drives as seen through the explorer.
Removal disk L: is a thumb drive and volume I: has been mounted on folder F:\mymntpoint. All these things configured to demonstrates some of the volume management functions usage.
The following program example uses FindFirstVolume() to search the first volume and GetVolumeInformation() to extract some of the volume information.
// for Win Xp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
#define BUFSIZE MAX_PATH
#define FILESYSNAMEBUFSIZE MAX_PATH
int main()
{
char buf[BUFSIZE]; // buffer for unique volume identifiers
DWORD lpMaximumComponentLength;
DWORD dwSysFlags; // flags that describe the file system
char FileSysNameBuf[FILESYSNAMEBUFSIZE];
// handle for the volume search
HANDLE hVol;
// open a scan for volumes.
hVol = FindFirstVolume(buf, BUFSIZE);
if(hVol == INVALID_HANDLE_VALUE)
{
printf ("No volumes found!\n");
return (-1);
}
BOOL test = GetVolumeInformation(
buf,
NULL,
BUFSIZE,
NULL,
&lpMaximumComponentLength,
&dwSysFlags,
FileSysNameBuf,
FILESYSNAMEBUFSIZE
);
printf("The return value: %d\n", test);
printf("The first volume found: %s\n", buf);
printf("The buffer for volume name: %d\n", BUFSIZE);
printf("The max component length: %d\n", lpMaximumComponentLength);
printf("The file system flag: %d\n", dwSysFlags);
printf("The file system: %s\n", FileSysNameBuf);
printf("The buffer for file system name: %d\n", FILESYSNAMEBUFSIZE);
CloseHandle(hVol);
return 0;
}
A sample output:
The return value: 1
The first volume found: \\?\Volume{a3446ed5-ebd9-11d8-a25c-806d6172696f}\
The buffer for volume name: 260
The max component length: 255
The file system flag: 459007
The file system: NTFS
The buffer for file system name: 260
Press any key to continue
A VC++ 2005 sample output.
The following program example uses FindFirstVolume() to search the first volume, FindNextVolume() to search other volumes, GetVolumeInformation() to extract some of the volume information and FindVolumeClose() to close the find volume handle.
The output has been trimmed.
// for Win Xp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
#define BUFSIZE MAX_PATH
#define FILESYSNAMEBUFSIZE MAX_PATH
BOOL ProcessVolume(HANDLE hVol, char *Buf, int iBufSize)
{
DWORD lpMaximumComponentLength;
DWORD dwSysFlags; // flags that describe the file system
char FileSysNameBuf[FILESYSNAMEBUFSIZE];
BOOL bFlag; // generic results flag
GetVolumeInformation(
Buf,
NULL,
BUFSIZE,
NULL,
&lpMaximumComponentLength,
&dwSysFlags,
FileSysNameBuf,
FILESYSNAMEBUFSIZE
);
////////----------caution--------------///////
// for file system, in order the removal drives such as floppy
// and CD-ROM to be recognized, you must insert the media...
printf("The volume found: %s\n", Buf);
printf("The buffer for volume name: %d\n", BUFSIZE);
printf("The max component length: %d\n", lpMaximumComponentLength);
printf("The file system flag: %d\n", dwSysFlags);
printf("The file system: %s\n", FileSysNameBuf);
printf("The buffer for file system name: %d\n\n", FILESYSNAMEBUFSIZE);
bFlag = FindNextVolume(
hVol, // handle to search being conducted
Buf, // pointer to output
iBufSize // size of output buffer
);
return (bFlag);
}
int main()
{
char buf[BUFSIZE]; // buffer for unique volume identifiers
HANDLE hVol; // handle for the volume scan
BOOL bFlag;
// open a search for volumes.
hVol = FindFirstVolume(buf, BUFSIZE);
if(hVol == INVALID_HANDLE_VALUE)
{
printf("No volumes found!\n");
return (-1);
}
bFlag = ProcessVolume(hVol, buf, BUFSIZE);
// do while we have volumes to process.
while(bFlag)
{ bFlag = ProcessVolume(hVol, buf, BUFSIZE); }
// close out the volume search and close the handle
bFlag = FindVolumeClose(hVol);
return 0;
}
The output (has been trimmed):
...
...
The volume found: \\?\Volume{a3446edb-ebd9-11d8-a25c-806d6172696f}\
The buffer for volume name: 260
The max component length: 255
The file system flag: 459007
The file system: NTFS
The buffer for file system name: 260
The volume found: \\?\Volume{a3446ed3-ebd9-11d8-a25c-806d6172696f}\
The buffer for volume name: 260
The max component length: 110
The file system flag: 524293
The file system: CDFS
The buffer for file system name: 260
The volume found: \\?\Volume{a3446ed2-ebd9-11d8-a25c-806d6172696f}\
The buffer for volume name: 260
The max component length: 255
The file system flag: 524294
The file system: FAT
The buffer for file system name: 260
The volume found: \\?\Volume{2faa8876-ec06-11d8-adbf-00508de5770d}\
The buffer for volume name: 260
The max component length: 255
The file system flag: 6
The file system: FAT
The buffer for file system name: 260
Press any key to continue
The following program example uses GetVolumeNameForVolumeMountPoint(), FindFirstVolumeMountPoint(), FindNextVolumeMountPoint(), GetVolumeInformation(), FindFirstVolumeMountPoint(), FindVolumeMountPointClose(), FindNextVolume(), FindFirstVolume(), FindVolumeClose().
// for Win Xp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
#define Bufsize MAX_PATH
#define FILESYSNAMEBufsize MAX_PATH
// process each mount point found here. The result indicates whether there is
// another mount point to be searched. This routine prints out the path to a mount point and its target.
BOOL ProcessVolumeMountPoint(HANDLE hPt, char *PtBuffer, DWORD dwPtBufsize, char *Buffer, DWORD dwBufsize)
{
BOOL bFlag; // Boolean result
char Path[Bufsize]; // construct a complete path here
char Target[Bufsize]; // target of mount at mount point
printf("Volume mount point found is \"%s\"\n", PtBuffer);
// detect the volume mounted there. Build a unique path to the mount point
// strcpy_s(Path, Bufsize, Buffer);
strcpy(Path, Buffer);
// strcat_s(Path, Bufsize, PtBuffer);
strcat(Path, PtBuffer);
bFlag = GetVolumeNameForVolumeMountPoint(
Path, // input volume mount point or directory
Target, // output volume name buffer
Bufsize); // size of volume name buffer
if(!bFlag)
printf("Attempt to get volume name for %s failed.\n", Path);
else
printf("Target of the volume mount point is %s.\n\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
PtBuffer, // pointer to output string
dwPtBufsize); // size of output buffer
return (bFlag);
}
// process each volume. The Boolean result indicates whether there is another volume to be searched.
BOOL ProcessVolume(HANDLE hVol, char *Buffer, int iBufsize)
{
BOOL bFlag; // generic results flag for return
HANDLE hPt; // handle for mount point scan
char PtBuffer[Bufsize]; // string buffer for mount points
DWORD dwSysFlags; // flags that describe the file system
char FileSysNameBuffer[FILESYSNAMEBufsize];
printf("Volume found is \"%s\".\n", Buffer);
// is this volume NTFS or other?
GetVolumeInformation(Buffer, NULL, 0, NULL, NULL, &dwSysFlags, FileSysNameBuffer, FILESYSNAMEBufsize);
////////----------caution--------------///////
// for file system, in order the removal drives such as floppy
// and CD-ROM to be recognized, you must insert the media...
printf("The file system is %s\n", FileSysNameBuffer);
// detect support for reparse points, and therefore for volume
// mount points, which are implemented using reparse points.
if(!(dwSysFlags & FILE_SUPPORTS_REPARSE_POINTS))
{ printf("This file system does not support volume mount points.\n\n"); }
else
{
// start processing mount points on this volume.
hPt = FindFirstVolumeMountPoint(
Buffer, // root path of volume to be scanned
PtBuffer, // pointer to output string
Bufsize); // size of output buffer
if(hPt == INVALID_HANDLE_VALUE)
{printf("No volume mount points found!\n\n");}
else
{
// process the volume mount point.
bFlag = ProcessVolumeMountPoint(hPt, PtBuffer, Bufsize, Buffer, Bufsize);
// do while we have volume mount points to process.
while (bFlag)
bFlag = ProcessVolumeMountPoint(hPt, PtBuffer, Bufsize, Buffer, Bufsize);
FindVolumeMountPointClose(hPt);
}
}
// stop processing mount points on this volume.
bFlag = FindNextVolume(
hVol, // handle to scan being conducted
Buffer, // pointer to output
iBufsize); // size of output buffer
return (bFlag);
}
int main()
{
char Buffer[Bufsize]; // buffer for unique volume identifiers
HANDLE hVol; // handle for the volume scan
BOOL bFlag; // generic results flag
// open a search for volumes.
hVol = FindFirstVolume(Buffer, Bufsize);
if(hVol == INVALID_HANDLE_VALUE)
{
printf("No volumes found!\n");
return (-1);
}
bFlag = ProcessVolume(hVol, Buffer, Bufsize);
// do while we have volumes to process.
while(bFlag)
{bFlag = ProcessVolume(hVol, Buffer, Bufsize);}
// close out the volume scan, handle to be closed
bFlag = FindVolumeClose(hVol);
return (bFlag);
}
The output sample:
Volume found is "\\?\Volume{a3446ed5-ebd9-11d8-a25c-806d6172696f}\".
The file system is NTFS
No volume mount points found!
Volume found is "\\?\Volume{a3446ed6-ebd9-11d8-a25c-806d6172696f}\".
The file system is NTFS
No volume mount points found!
Volume found is "\\?\Volume{a3446ed7-ebd9-11d8-a25c-806d6172696f}\".
The file system is NTFS
Volume mount point found is "mymntpoint\"
Target of the volume mount point is \\?\Volume{a3446edb-ebd9-11d8-a25c-806d6172696f}\.
Volume found is "\\?\Volume{a3446ed8-ebd9-11d8-a25c-806d6172696f}\".
The file system is NTFS
No volume mount points found!
Volume found is "\\?\Volume{a3446ed9-ebd9-11d8-a25c-806d6172696f}\".
The file system is NTFS
No volume mount points found!
Volume found is "\\?\Volume{a3446eda-ebd9-11d8-a25c-806d6172696f}\".
The file system is NTFS
No volume mount points found!
Volume found is "\\?\Volume{a3446edb-ebd9-11d8-a25c-806d6172696f}\".
The file system is NTFS
No volume mount points found!
Volume found is "\\?\Volume{a3446ed3-ebd9-11d8-a25c-806d6172696f}\".
The file system is CDFS
This file system does not support volume mount points.
Volume found is "\\?\Volume{a3446ed2-ebd9-11d8-a25c-806d6172696f}\".
The file system is FAT
This file system does not support volume mount points.
Volume found is "\\?\Volume{2faa8876-ec06-11d8-adbf-00508de5770d}\".
The file system is FAT
This file system does not support volume mount points.
Press any key to continue
A sample output run on VC++ 2005.
Check the best selling C, C++ and Windows books at Amazon.com.
Microsoft Visual C++, online MSDN.
ReactOS - Windows binary compatible OS - C/C++ source code repository, Doxygen.
Notation used in MSDN is Hungarian Notation instead of CamelCase and is discussed VC++ programming notations.
Windows data type information is in Data types used in Windows programming.
For Multibytes, Unicode characters and Localization please refer to Locale, wide characters & Unicode (Story) and Windows users & groups programming tutorials (Implementation).
Structure, enum, union and typedef story can be found C/C++ struct, enum, union & typedef.
C & C++ Programming Tutorial | C Programming Practice