什么是“卷”?
卷,又称为“逻辑驱动器”,是 NTFS, FAT32 等文件系统组织结构的最高层。卷是存储设备(如硬盘)上由文件系统管理的一块区域,是在逻辑上相互隔离的存储单元。一个磁盘分区至少包含一个卷,当然卷也可以存在于多个磁盘分区上,仅存在于一个分区上的卷称为“简单卷“,存在于多个磁盘分区上的卷称为”多分区卷“或”跨区卷“。最为常见的情况是一个分区只包含 一个卷,一个卷只存在于一个分区上,所以往往会造成的混淆是卷等于分区。卷存在卷标,程序可以通过卷标访问卷。

卷挂接在 Unix/Linux/Netware 系统上应用比较常见,Windows 可能由于多用于个人平台,所以知道卷挂接技术的人就比例上来说少了很多。你可以将它理解为:把一个物理设备挂接到一个逻辑盘符或文件夹中来使用,例如:如果需要扩展 C 盘的容量,而 C 盘所在的分区/磁盘已没有空闲空间来扩展它时,可以加装一个 200GB 的新硬盘,然后在 C: 中新增一个目录 ExtDisk,并将这个新磁盘挂接到这个目录中即可,现在 C: 盘的容量就增加了 200GB。有一点要注意,就是卷挂接只能用于 NTFS 系统。

4.2.1 遍历卷并获取属性
获取一个主机上的所有驱动器列表有两种方法,一种是使用 GetLogicalDrives 或
GetLogicalDriveStrings,另一种是使用 FindFirstVolume 和 FindNextVolume 组合。
第一种方法获取主机上的逻辑驱动器,也就是所有分配的卷标的驱动器,返回的结果是
驱动器的根路径。第二种方法返回的是“\\?\volume{GUID}”形式的驱动器设备名。
使用 GetDriveType API 可以获取驱动器类型,使用 GetVolumeInformation 可以获取驱
动器属性。
1.关键 API
(1) GetLogicalDrives。
获取主机中所有的逻辑驱动器,以 BitMap 的形式返回,其函数原型如下:
◇返回值
GetLogicalDrive 函数返回一个 DWORD 类型的值,第一位表示所对应的驱动器是否存在。
一般情况下 DWORD 的数据长度是 32 位,在这个 DWORD 中,每一位对应了一个逻辑驱动器是
否存在。第二位如果是“1”则表示驱动器“B:”存在,第 4 位如果是“1”则表示驱动器
“D:”是存在的,以此类推。
(2) GetLogicalDriverStrings。
获取主机中所有驱动器,以驱动器根路径字符串返回,其函数原型如下:
◇参数
nBufferLength:参数 lpBuffer 所指向的内存空间的大小,以字节为单位。
lpBuffer:指向存储返回结果字符串的内存空间。
◇返回值
函数的返回值指明了函数调用是否成功,如果成功则返回缓冲区中返回结果的总长度。
如果返回值大于 nBufferLength,说明给定的缓冲区大小不够,返回值是实际需要的大小。
如果返回 0,则说明函数运行出错。
◇使用说明
这个 API 实现了与 GetLogicalDrives 同样的功能,却以一种更直观的方式返回执行结
果。函数执行结果放在 lpBuffer 所指向的内存区域中,此内存区域大小由 nBufferLength
参数指定,使函数返回结果不至于溢出。在调用此函数前需保证内存分配。
函数调用成功后,将在缓冲区中依次填入本机所具有的驱动器根路径字符串,如在笔者
系统中有 5 个逻辑驱动器“C:\”、“D:\”“E:\”、“F:\”、“I:\”。执行后在缓冲
区中的结果如下:
也就是连续放置了“C:\”、“D:\”“E:\”、“F:\”、“I:\”这 5 个字符串(会
在每个字符串后加一个‘\o’结束符,在所有卷标字符串的最后再加一个结束符)。
(3)FindFirstVolume。
查找主机中的第一个驱动器,返回驱动器设备名,其函数原型如下:
◇参数
lpszVolumeName:指向驱动器名的内存缓冲区。
cchBufferLength:参数 lpszVolumeName 所指向的缓冲区大小,以字节为单位。
◇返回值
驱动器查找句柄, F 猫 NextVolume 和 FindVolumeColse 的参数, 如果执行失败, 返回 NULL。
(4)FindNextVolume
查找主机中后继的逻辑驱动器,其函数原型如下:
◇参数
hFindVolume: FindFirstVolume 所返回的驱动器查找句柄。
lpszVolumeName:指向保存驱动器名的内存缓冲区。
cchBufferLength:参数 lpszVolumeName 所指向的缓冲区大小,以字节为单位。
◇返回值
返回 BOOL 表示是否成功,如果失败说明已经查找完成所有逻辑驱动器。
(5)FindVo1umeClose。
\关闭 FindFirstVolume 打开的卷遍历句柄,其函数原型如下:
◇参数
hFindVolume:要关闭的驱动器查找句柄。
◇返回值
返回 BOOL 值表示是否成功关闭句柄。
(6) GetDriveType。
获取驱动器类型,其函数原型如下:
◇参数
lpRootPathIName:驱动器根路径,如“C:\”。
◇返回值 /
驱动器的类型,如 DRIVE' FIXED 表示硬盘,DRIVE_CDROM 表示光盘等。详见实例 4-2
的 GetDirverInfo 函数。
(7) GetVolumeInformation。
获取逻辑驱动器信息,其函数原型如下:
◇参数
lpRootPathName:输入参数,指向所要获取属性的驱动器的根路径字符串。
lpVolumeNameBuffer:输出参数,返回驱动器名。

GetLogicalDriveStrings枚举磁盘,然后可以调用GetDiskFreeSpaceEx获取大小信息。

GetLogicalDrives

DWORD WINAPI GetLogicalDrives(void);

该函数没有参数,返回值为DWORD,是一个位掩码代表当前的磁盘驱动器。第0位表示驱动器A,第二位表示驱动器B。以此类推,某一位为1表示存在驱动器,为0表示不存在。

 
void GetDisksInformation()
{
printf("Begin Call GetDisksInformation()\n");
DWORD dwDisk = GetLogicalDrives();
int dwMask = 1;
int step = 1;
dwMask<<1;
while (step < 32)
{
++step;
switch (dwMask&dwDisk)
{
case 1:
printf("volume A\n");
break;
case 2:
printf("volume B\n");
break;
case 4:
printf("volume C\n");
break;
case 8:
printf("volume D\n");
break;
case 32:
printf("volume E\n");
break;
case 64:
printf("volume F\n");
break;
case 128:
printf("volume G\n");
break;
case 256:
printf("volume H\n");
break;
default:
break;
}
dwMask = dwMask<<1;
}
printf("end Call GetDisksInformation()\n");
}

 
GetLogicalDriveStrings
DWORD WINAPI GetLogicalDriveStrings(
_In_   DWORD nBufferLength,
_Out_  LPTSTR lpBuffer
);
lpBuffer ,存储驱动器根路径字符串的缓冲区内存
nBufferLength 缓冲区 的大小
void GetDisksInformationEx()
{
printf("Begin Call GetDisksInformationEx()\n");
CHAR szLogicalDriveString[BUFFERSIZE];
PCHAR szDrive; ZeroMemory(szLogicalDriveString,BUFFERSIZE);
GetLogicalDriveStrings(BUFFERSIZE - 1, szLogicalDriveString);
szDrive = szLogicalDriveString;
while (*szDrive)
{
printf("volume %s\n",szDrive);
szDrive += (lstrlen(szDrive) + 1);
}
printf("end Call GetDisksInformationEx()\n");
}

 
 

FindFirstVolume

 
HANDLE WINAPI FindFirstVolume(
_Out_  LPTSTR lpszVolumeName, //驱动器名的缓冲区
_In_   DWORD cchBufferLength //缓冲区的大小
);

返回值为驱动器的句柄

该函数用来查找主机上第一个驱动器,返回驱动器名。
 
BOOL WINAPI FindNextVolume(
_In_   HANDLE hFindVolume, //调用FindFirstVolume返回的驱动器句柄
_Out_  LPTSTR lpszVolumeName, //驱动器名的缓冲区
_In_   DWORD cchBufferLength //缓冲区的大小
);

查找下一个驱动器

 
BOOL WINAPI FindVolumeClose(
_In_  HANDLE hFindVolume //调用FindFirstVolume返回的驱动器句柄 );

该函数用来关闭一个驱动器的句柄。被关闭的句柄就不能再在FindNextVolume或者FindVolumeClose中使用了。

 
void FindVolume()
{
printf("Begin Call FindVolume()\n");
CHAR szVolume[MAX_PATH];
HANDLE hVolume;
ZeroMemory(szVolume,MAX_PATH);
hVolume = FindFirstVolume(szVolume,MAX_PATH);
if (hVolume == INVALID_HANDLE_VALUE)
{
printf("Not found the first volume\n");
}
printf("volume %s\n",szVolume);
while (FindNextVolume(hVolume,szVolume,MAX_PATH))
{
printf("volume %s\n",szVolume);
}
FindVolumeClose(hVolume);
printf("end Call FindVolume()\n");
}

 
 
 
 
 
 
 

#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#define  BUFSIZE MAX_PATH

BOOL GetDirverInfo(LPSTR szDrive);

int main(void)
{
TCHAR buf[BUFSIZE];
HANDLE hVol;
BOOL bFlag;
/**********************************
* FindFirstVolume(buf,BUFSIZE)
* 功能:查找主机中的第一个驱动器
* 参数:buf,BUFSIZE
* buf 指向驱动器名的内存缓存区
* BUFSIZE 参数buf所指向的缓存区大小
* 返回值 HANDLE :驱动器设备名
**********************************/
hVol = FindFirstVolume(buf,BUFSIZE);

if (hVol == INVALID_HANDLE_VALUE)
{
printf(TEXT("No volmes found!\n"));
return (-1);
}
GetDirverInfo(buf);
while(FindNextVolume(hVol,buf,BUFSIZE))
{
GetDirverInfo(buf);
}
bFlag = FindVolumeClose(hVol);
char ch;
ch = getchar();
return (bFlag);
}

//GetDirverInfo函数

BOOL GetDirverInfo(LPSTR szDrive)
{
UINT uDiveType;
DWORD dwVolumeSerialNumber;
DWORD dwMaximumComponentLength;
DWORD dwFileSystemFlags;
CHAR szFileSystemNameBuffer[BUFSIZE];
CHAR szDirverName[MAX_PATH];
printf("\n%s\n",szDrive);
/*********************
* UINT WINAPI GetDriveType(LPSTR szDrive);
* 功能:判断一个磁盘驱动器的类型
* 参数:LPSTR szDrive 
* 指明要获取属性的驱动器的根目录,如C:\
* 返回值 UINT:表示磁盘类型
**********************/
uDiveType = GetDriveType(szDrive);
switch(uDiveType)
{
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 removable 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://RAM
printf("The drive is a RAM disk.");
break;
default:
break;
}
/***********************************
*GetVolumeInformation(szDrive,szDirverName,MAX_PATH,
&dwVolumeSerialNumber,&dwMaximumComponentLength,
&dwFileSystemFlags,szFileSystemNameBuffer,BUFSIZE)
* 功能:获取磁盘驱动器的信息
* 参数:如下
* 返回值:非零即成功
***********************************/
if (!GetVolumeInformation(szDrive,
szDirverName,//卷标(字符串)
MAX_PATH,//szDirveName的长度
&dwVolumeSerialNumber,//用于装载磁盘卷序列号的变量
&dwMaximumComponentLength,//用于装载文件名每一部分的长度
&dwFileSystemFlags,//用于装载一个或多个二进制位标志的变量
szFileSystemNameBuffer,//系统类型
BUFSIZE))
{
return FALSE;
}
if (0!=lstrlen(szDirverName))
{
printf("\nDrive Name is %s\n",szDirverName);
}
printf("\nVolume Serial Number is %u",dwVolumeSerialNumber);
printf("\nMaximun 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 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 supports case-sensitive file names.\n");
}
printf("...\n");
return TRUE;
}

FindFirstVolume系列函数遍历驱动器,获取驱动器信息的更多相关文章

  1. Python调用ansible API系列(一)获取资产信息

    你想让ansible工作首先就需要设置资产信息,那么我们如何通过使用Python调取Ansible的API来获取资产信息呢? 要提前准备一个hosts文件 获取组或者主机 #!/usr/bin/env ...

  2. html5获取地理位置信息API

    html5获取地理位置信息API 在HTML5中,可以看下如何使用Geolocation API来获得用户的地理位置信息,如果该浏览器支持的话,且设备具有定位功能,就能够直接使用这组API来获取当前位 ...

  3. thinkphp5.0 获取请求信息

    如果要获取当前的请求信息,可以使用\think\Request类,除了下文中的 $request = Request::instance(); 也可以使用助手函数 $request = request ...

  4. openssl之EVP系列之9---EVP_Digest系列函数的一个样例

    openssl之EVP系列之9---EVP_Digest系列函数的一个样例     ---依据openssl doc/crypto/EVP_DigestInit.pod翻译     (作者:Drago ...

  5. openssl之EVP系列之10---EVP_Sign系列函数介绍

    openssl之EVP系列之10---EVP_Sign系列函数介绍     ---依据openssl doc/crypto/EVP_SignInit.pod翻译     (作者:DragonKing, ...

  6. 微信小程序~App.js中获取用户信息

    (1)代码:主要介绍下获取用户信息部分 onLaunch: function () { // 展示本地存储能力 var logs = wx.getStorageSync('logs') || [] l ...

  7. OpenSSL EVP_Digest系列函数的一个样例

    #include <stdio.h>     #include <openssl/evp.h>         main(int argc, char *argv[])     ...

  8. [WinAPI] API 5 [遍历驱动器并获取驱动器属性]

    (1) GetLogicalDrives.获取主机中所有的逻辑驱动器,以BitMap的形式返回.◇返回值GetLogicalDrive函数返回一个DWORD类型的值,第一位表示所对应的驱动器是否存在. ...

  9. 【转】windows c++获取文件信息——_stat函数的使用

    _stat函数的功能 _stat函数用来获取指定路径的文件或者文件夹的信息. 函数声明 int _stat( const char *path, struct _stat *buffer ); 参数: ...

随机推荐

  1. springmvc4+hibernate4+activiti5.18(Maven)

    项目下载地址: http://files.cnblogs.com/files/walk-the-Line/springmvc_activiti5.18_hibernate4.zip

  2. bzoj1861 书架 splay版

    单点插入删除以及求前缀 #include<cstdio> #include<cstring> #include<algorithm> using namespace ...

  3. 【Mysql优化】聚簇索引与非聚簇索引概念

    必须为主键字段创建一个索引,这个索引就是所谓的"主索引".主索引与唯一索引的唯一区别是:前者在定义时使用的关键字是PRIMARY而不是UNIQUE.  首先明白两句话: innod ...

  4. UVALIVE 2686 Stargates

    尼玛真深坑合时p[x] = y 就RE,p[y] = x 就AC . #include <map> #include <set> #include <list> # ...

  5. 使用Python获取计算机名,ip地址,mac地址等等

    获取计算机名 # 获取计算机名,常用的方法有三种 import os import socket # method one name = socket.gethostname() print(name ...

  6. [ Python - 6 ] 正则表达式实现计算器功能

    要求:禁止使用eval函数.参考网上代码如下: #!_*_coding:utf-8_*_ """用户输入计算表达式,显示计算结果""" im ...

  7. hdu 1147(线段相交)

    Pick-up sticks Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)To ...

  8. PostgreSQL9.6.3的REDIS测试

    安装redis_fdwcd /usr/local/srcgit clone https://github.com/pg-redis-fdw/redis_fdw.gitcd redis_fdw/git ...

  9. Ubuntu-16.04安装Xdebug-2.2.5及相关介绍

    Xdebug是一个开放源代码的PHP程序调试器(即一个Debug工具),可以用来跟踪,调试和分析PHP程序的运行状况.在日常开发中,我们会使用如 print_r() var_dump()等函数来进行调 ...

  10. PHP无限极分类详谈

    当你学习php无限极分类的时候,大家都觉得一个字“难”我也觉得很难,所以,现在都还在看,因为工作要用到,所以,就必须得研究研究. 到网上一搜php无限极分类,很多,但好多都是一个,并且,写的很乱,代码 ...