一、概述
1.基本概念
(1)磁盘分区(Partitions)
(2)卷(Volumes):是存储设备上有文件系统管理区域的一块区域,是在逻辑上的相互隔离的存储单元。
2.文件系统的主要API
(1)磁盘和驱动器管理类API
(2)文件和目录管理
(3)高级文件系统操作
二、磁盘和驱动器管理
1.遍历卷并获取属性
获取一个主机上的所有驱动器列表有两种方法,一种是使用GetLogicalDrives或GetLogicalDrivesStrings;另一种是使用FindNextVolume组合。
(1)GetLogicalDrives
功能:获取主机中所有的逻辑驱动器,以Bitmap的形式返回
函数原型:DWORD GetLogicalDrives(void);
返回值:GetLogicalDrives返回一个DWORD类型的值,第一位表示所对应的驱动器是否存在。
(2)GetLogicalDrivesStrings
功能:获取主机中所有的逻辑驱动器,以驱动器根路径字符串返回。
函数原型:DWORD GetLogicalDrivesStrings(
DWORD nBufferLength,
LPTSTR lpBuffer //函数的返回结果存在lpBuffer所指向的内存区域中
);
参数:
nBufferLength:参数lpBuffer所指向的内存空间的大小,以字节为单位。
lpBuffer:指向存储返回结果字符串的内存空间。
返回值:
函数的返回值指明函数调用是否成功,如果成功则为缓存区中返回结果的总长度。如果返回值大于nBufferLength,说明给定的缓冲区大小不够,返回值是实际需要的大小。如果返回0,则说明函数运行出错。
(3)FindFirstVolume
功能:查找主机中的第一个驱动器,返回驱动器设备名
函数原型:
HANDLE FindFirstVolume(
LPTSTR lpszVolumName,
DWORD cchBufferLength
);
参数:
lpszVolumName:指向驱动器名的内存缓冲区。
cchBufferLength:参数lpszVolumName所指向的缓冲区大小,以字节为单位。
返回值:
驱动器查找句柄,可作为FindNextVolume和FindVolumeClose的参数,如果执行失败,返回NULL。
(4)FindNextVolume
功能:查找主机后继的逻辑驱动器
BOOL FindNextVolume(
HANDLE hFindVolume,
LPTSTR lpszVolumeName,
DWORD cchBufferLength
);
参数:
hFileVolume:FindFirstVolume所返回的驱动器查找句柄。
lpszVolumeName:指向保存驱动器的内存缓冲区。
cchBufferLength:参数lpszVolumeName所指向的缓冲区大小,以字节为单位。
返回值:
返回BOOL表示是否成功,如果失败说明已经查找所有的逻辑驱动器。
(5)FindVolumeClose
功能:关闭FindFirstVolume打开的卷遍历句柄
函数原型:
BOOL WINAPI FindVolumeClose(
HANDLE hFileVolume
);
参数:
hFindVolume:要关闭的驱动器查找句柄。
返回值:
返回BOOL值表示是否成功关闭句柄。
(6)GetDriveType
功能:获取驱动器类型
函数原型:
UINT GetDriveType(
LPCTSTR lpRootPathName
);
参数:
lpRootPathName:驱动器根路径,如“C:\”。
返回值:
驱动器类型,如DRIVE_FIXED表示硬盘,DRIVE_CDROM表示光盘等。
(7)GetVolumeInformation
功能:获取逻辑驱动器信息
函数原型:
BOOL GetVolumeInfomation(
LPCTSTR lpRootPathName,
LPTSTR lpVolumeNameBuffer,
DWORD nVolumeNameSize,
LPDWORD
lpVolumeSerialNumber,
LPDWORD lpMaximumComponentLength,
LPDWORD lpFileSystemFlags,
LPTSTR lpFileSystemNameBuffer,
DWORD nFileSystemNameSize
);
参数:
lpRootPathName:输入参数,指向所要获取属性的驱动器的根路径字符串。
lpvolumeNameBuffer:输出参数,返回驱动器名。
nVolumeNameSize:输入参数,lpVolumeNameBuffer的内存缓冲区的大小。
lpVolumeSerialNumber:输出参数,存储驱动器序列号。
lpMaximumComponentLength:输出参数,返回文件系统所支持的文件组成部分的最大值。
lpFileSystemFlags:输出参数,属性可以用来判断多种驱动器属性值,如FILE_VOLUME_QUOTAS表示支持磁盘配额,
FILE_SUPPORTS_ENCRYPTION表示文件系统是否是支持EFS加密等。
lpFileSystemNameBuffer:输出参数,表示文件类型,如“NTFS”,“CDFS”等。
nFileSystemNameSize:lpFileSystemNameBuffer的缓冲区的大小。
返回值:
返回BOOL值,表示信息获取是否成功。
2.使用GetLogicalDriveStrings获取驱动器的根路径
/* **********************************************************
* GetVolumeInfo.c 遍历驱动器获取驱动器属性
* *********************************************************/
/*头文件*/
#include <Windows.h>
#include <stdlib.h>
#include <stdio.h>
/*预定义*/
#define BUFSIZE 1024
/*函数申明*/
BOOL GetDirverInfo(LPSTR szDrive);
/* **********************************************************
* 应用程序主函数,遍历驱动器并调用GetDirverInfo,获取驱动器属性
* **********************************************************/
void main(void)
{
CHAR szLogicalDriveStrings[BUFSIZE];
PCHAR szDrive;
ZeroMemory(szLogicalDriveStrings,BUFSIZE);
//获取逻辑驱动器卷标名
GetLogicalDriveStrings(BUFSIZE - 1,szLogicalDriveStrings);
szDrive = (PCHAR)szLogicalDriveStrings;
//循环处理每个卷
do
{
if (!GetDirverInfo(szDrive))
{
printf("\n Get Volume Infomation Error :%d",GetLastError());
}
szDrive += (lstrlen(szDrive) + 1);
} while (* szDrive != '\x00');
}
3.使用FindFirstVolume系列函数遍历驱动器,获取驱动器信息
/* *****************************************************************
* Enumeratevolume.c 遍历驱动器并获取驱动器属性
* ****************************************************************/
#define _WIN32_WINNT 0x0501
/*头文件*/
#include <Windows.h>
#include <stdio.h>
/*预定义*/
#define BUFSIZE MAX_PATH
/*函数申明*/
BOOL GetDirverInfo(LPSTR szDrive);
/* ******************************************************************
* 功能 :应用程序主函数,遍历驱动器并调用
* ******************************************************************/
int main(void)
{
TCHAR buf[BUFSIZE];
//卷标信息
HANDLE hVol;
//卷遍历句柄
BOOL bFlag;
hVol = FindFirstVolume(buf, BUFSIZE);
if (hVol == INVALID_HANDLE_VALUE)
{
printf(TEXT("No Volumes Found!\n"));
return (-1);
}
GetDirverInfo(buf);
while (FindNextVolume(
hVol,
buf,
BUFSIZE
))
{
GetDirverInfo(buf);
}
bFlag = FindVolumeClose(hVol);
return (bFlag);
}
4.调用GetVolumeInformation API函数,获取驱动器相关属性
/* ***************************************************
* BOOL GetDirverInfo(LPSTR szDrive)
* 功能:获取驱动器属性
* 参数:LPSTR szDrive
指明要获取属性的驱动器的根路径,如C:\
* 返回值BOOL:表示是否成功
* **************************************************/
BOOL GetDirverInfo(LPSTR szDrive)
{
UINT uDriveType;
DWORD dwVolumeSerialNumer;
DWORD dwMaximumComponentLength;
DWORD dwFileSystemFlags;
CHAR szFileSystemNameBuffer[BUFSIZE];
CHAR szDirveName[MAX_PATH];
printf("\n %s \n",szDrive);
uDriveType = GetDriveType(szDrive);
switch(uDriveType)
{
case DRIVE_UNKNOWN:
printf("The drive type cannot be determined.");
break;
case DRIVE_NO_ROOT_DIR:
printf("The root path is invalid ,for example ,no volume is mounted at the path.");
break;
case DRIVE_REMOVABLE:
printf("The drive is a type that has removeble media ,for example ,a floppy drive or removable hard disk.");
break;
case DRIVE_FIXED:
printf("The drive is a type that cannot be removed ,for example ,a fixed hard drive.");
break;
case DRIVE_REMOTE:
printf("The drive is a remote (network) drive.");
break;
case DRIVE_CDROM:
printf("The drive is a CD_ROM drive.");
break;
case DRIVE_RAMDISK:
printf("The drive is a RAM disk.");
break;
default:
break;
}
if (!GetVolumeInformation(
szDrive,
szDirveName,
MAX_PATH,
&dwVolumeSerialNumer,
&dwMaximumComponentLength,
&dwFileSystemFlags,
szFileSystemNameBuffer,
BUFSIZE))
{
return FALSE;
}
if (0 != lstrlen(szDirveName))
{
printf("\n Drive Name is %s\n",szDirveName);
}
printf("\n Volume Serial Number is %u ",dwVolumeSerialNumer);
printf("\n Maxinum component Length is %u",dwMaximumComponentLength);
printf("\nSystem type is %s \n",szFileSystemNameBuffer);
if (dwFileSystemFlags & FILE_SUPPORTS_REPARSE_POINTS)
{
printf("The file system does not support volume volume mount points .\n");
}
if (dwFileSystemFlags & FILE_VOLUME_QUOTAS)
{
printf("The file system supports disk quotas.\n");
}
if (dwFileSystemFlags & FILE_CASE_SENSITIVE_SEARCH)
{
printf("The file system support case-sensitive file name.\n");
}
printf("……\n");
return ture;
}
三、驱动器挂载点
挂载点实际上是操作系统挥着用户设置的,用来进入一个逻辑驱动器或者卷的入口。在设置了卷的挂载点后,用户或者应用程序可以使用卷标或者指定的挂载点进入卷。
1.关键API
(1)FindFirstVolumeMountPoint
功能:获取指定卷的第一个挂载点
函数原型:
HANDLE FindFirstVolumeMountPoint(
LPTSTR lpszRootPathName,
LPTSTR lpszVolumeMountPoint,
DWORD cchBufferLength
);
参数:
lpszRootPathName,输入参数,指定要查找的卷名,必须以反斜杠结尾
lpszVolumeMountPoint,输出参数,找到的第一个挂载点
cchBufferLength,输出参数,用来存储输出挂载点的缓存大小
返回值:
返回HANDLE值,为一个查找句柄,FindNextVolumeMountPoint用该句柄查找下一个挂载点。错误时值为INVALID_HANDLE_VALUE,并且可以使用GetLastError()函数获取详细的错误信息。
(2)FindNextVolumeMountPoint
功能:查找指定卷的后继挂载点
函数原型:
BOOL FindNextVolumeMountPoint(
HANDLE hFindVolumeMountPoint,
LPTSTR lpszVolumeMountPoint,
DWORD cchBufferLength
);
参数:
hFindVolumeMountPoint:输入参数,查找句柄,由hFindFirstVolumeMountPoint获取。
lpszFindVolumeMountPoint:输出参数,找到后继挂在点。
cchBufferLength:输入参数,用来存储输出挂载点的缓存大小。
返回值:
返回BOOL值,表示查找是否成功,失败并且GetLastError函数返回ERROR_NO_MORE_FILES代码时表示已经查找完所有的挂载点。
(3)FindVolumeMountPointClose
功能:关闭FindFirstVolumeMountPoint打开的卷句柄
函数原型:
BOOL FindVolumeMountPointClose(
HANDLE hFindVolumeMountPoint,
);
参数:
hFindVolumeMountPoint:要关闭的挂载点的查找句柄。
返回值:
返回BOOL值,是否成功关闭句柄。、
(4)GetVolumeNameForVolumeMountPoint
功能:查找指定卷的后继挂载点
函数原型:
GetVolumeNameForVolumeMountPoint(
LPTSTR lpszVolumeMountPoint,
LPTSTR lpszVolumeName,
DWORD cchBufferLength
)
参数:
lpsz
VolumeMountPoint:输入参数,指定需要查找挂载点或者根目录,以反斜杠结束。
lpszFindVolumeName:输出参数,挂载点对应的卷设备名,形式为"\\?\Volume{GUID}\"。
cchBufferLength:输入参数,用来存储输出设备名的缓存大小。
返回值:
返回BOOL值,表示函数是否成功,同样可以用GetLasterror()函数获取更详细的错误信息。
(5)SetVolumeMountPoint
功能:将指定卷挂在到指定的挂载点处
函数原型:
BOOL SetVolumeMountPoint(
LPCTSTR lpszVolumeMountPoint,
LPCTSTR lpszVolumeName
);
参数:
lpszVolumeMountPoint:输入参数,指定挂载点,挂载点必须为一个根路径或者一个现有卷上的路径,必须反斜杠结束。
lpszVolumeName:输入参数,卷设备名。
返回值:
返回BOOL值,表示函数是否成功,同样可以用GetLasterror()函数获取更详细的错误信息。
2.查找、设置挂载点,通过挂载点获取卷设备名
/* *********************************************************************
* mount.c卷挂载点操作
* *********************************************************************/
/*预编译声明*/
#define _WIN32_WINNT 0x0501
#include <Windows.h>
#include <stdio.h>
#include <tchar.h>
#define BUFSIZE MAX_PATH
#define FILESYSNAMEBUFSIZE MAX_PATH
/* ****************************************************************
* ProcessVolumeMountPoint
* 功能:列举挂载点
* ****************************************************************/
BOOL ProcessVolumeMountPoint(HANDLE hPt,
TCHAR *PtBuf,
DWORD dwPtBufSize,
TCHAR *Buf
)
{
BOOL bFlag; //结果
TCHAR Path[BUFSIZE]; //全路径
TCHAR Target[BUFSIZE]; //挂载点设备
printf("\tVolume mount point found is \"%s\"n",PtBuf);
lstrcpy(Path,Buf);
lstrcat(Path,PtBuf);
bFlag = GetVolumeNameForVolumeMountPoint(Path,
Target,
BUFSIZE
);
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);
}
bFlag = FindNextVolumeMountPoint(hPt,PtBuf,dwPtBufSize);
return bFlag;
}
/* **************************************************************************
* ProcessVolume
* 功能:判断卷类型,列举挂载点
* *************************************************************************/
BOOL ProcessVolume(HANDLE hVol,TCHAR *Buf,DWORD iBufSize)
{
BOOL bFlag; //返回标志
HANDLE hPt;
TCHAR PtBuf[BUFSIZE];
DWORD dwSysFlags;
TCHAR FileSysNameBuf[FILESYSNAMEBUFSIZE];
printf("Volume found is \"%s\".\n",Buf);
//是否为NTFS
GetVolumeInformation(Buf,NULL,0,NULL,NULL,&dwSysFlags,FileSysNameBuf,FILESYSNAMEBUFSIZE);
if (!(dwSysFlags & FILE_SUPPORTS_REPARSE_POINTS))
{
printf("\tThis file system does not support volume mount points.\n");
}
else
{
//本卷中的挂载点
hPt = FindFirstVolumeMountPoint(Buf,
PtBuf,
BUFSIZ
);
if (hPt == INVALID_HANDLE_VALUE)
{
printf("\tNo volume mount points found !\n");
}
else
{
//处理挂载点
bFlag = ProcessVolumeMountPoint(hPt,
PtBuf,
BUFSIZE,
Buf
);
//循环
while (bFlag)
{
bFlag = ProcessVolumeMountPoint(hPt,
PtBuf,
BUFSIZE,
Buf
);
}
//结束
FindVolumeMountPointClose(hPt);
}
}
//下一个
bFlag = FindNextVolume(hVol,
Buf,
iBufSize
);
return bFlag;
}
/* ***********************************************************************************
* int GetMountPoint(void)
* 功能:获取挂载点
* **********************************************************************************/
int GetMountPoint(void)
{
TCHAR buf[BUFSIZE]; //卷标识符
HANDLE hVol; //卷句柄
BOOL bFlag; //结束标识
printf("Volume mount points info of this computer:\n\n");
//打开卷
hVol = FindFirstVolume(buf,BUFSIZE);
if (hVol == INVALID_HANDLE_VALUE)
{
printf("No volume found!");
return -1;
}
bFlag = ProcessVolume(hVol,buf,BUFSIZE);
while(bFlag)
{
bFlag = ProcessVolume(hVol,buf,BUFSIZE);
}
bFlag = FindVolumeClose(hVol);
return bFlag;
}
/* ***********************************************************************
* void Usage(PCHAR argv)
* 功能:使用方法
* ***********************************************************************/
void Usage(PCHAR argv)
{
printf("\n\n\t%s,mount a volume at a mount point.\n",argv);
printf("\tFor example ,\"mount D:\\mnt\\drives\\E:\\\"\n");
}
/* ********************************************************************
* main
* 功能:入口函数
* ********************************************************************/
int main(int argc,PCHAR argv[])
{
BOOL bFlag;
CHAR Buf[BUFSIZE];
if (argc != 3)
{
GetMountPoint();
Usage(argv[0]);
return -1;
}
bFlag = GetVolumeNameForVolumeMountPoint(
argv[2], //输入挂载点或目录
Buf, //输出卷名
BUFSIZE
);
if (bFlag != TRUE)
{
printf("Retrieving volume name for %s failed.\n",argv[2]);
return -2;
}
printf("Volume name of %s is %s \n",argv[2],Buf);
bFlag = SetVolumeMountPoint(
argv[1], //挂载点
Buf //需要挂载的卷
);
if (!bFlag)
{
printf("Attempt to mount %s at %s failed.Error code is \n",argv[2],argv[1],GetLastError());
}
return bFlag;
}