zoukankan      html  css  js  c++  java
  • FindFirstVolume系列函数遍历驱动器,获取驱动器信息

    什么是“卷”?
    卷,又称为“逻辑驱动器”,是 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()
    ");
    	DWORD dwDisk = GetLogicalDrives();
    	int dwMask = 1;
    	int step = 1;
    	dwMask<<1;
    	while (step < 32)
    	{
    		++step;
    		switch (dwMask&dwDisk)
    		{
    		case 1:
    			printf("volume  A
    ");
    			break;
    		case 2:
    			printf("volume  B
    ");
    			break;
    		case 4:
    			printf("volume  C
    ");
    			break;
    		case 8:
    			printf("volume  D
    ");
    			break;
    		case 32:
    			printf("volume  E
    ");
    			break;
    		case 64:
    			printf("volume  F
    ");
    			break;
    		case 128:
    			printf("volume  G
    ");
    			break;
    		case 256:
    			printf("volume  H
    ");
    			break;
    		default:
    			break;
    		}
    		dwMask = dwMask<<1;
    	}
    	printf("end Call GetDisksInformation()
    ");
    }
    


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


     
     

    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()
    ");
    	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
    ");
    	}
    	printf("volume  %s
    ",szVolume);
    	while (FindNextVolume(hVolume,szVolume,MAX_PATH))
    	{
    		printf("volume  %s
    ",szVolume);
    	}
    	FindVolumeClose(hVolume);
    	printf("end Call FindVolume()
    ");
    }

     
     
     
     
     
     
     

    #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! "));
    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(" %s ",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(" Drive Name is %s ",szDirverName);
    }
    printf(" Volume Serial Number is %u",dwVolumeSerialNumber);
    printf(" Maximun Component Length is %u",dwMaximumComponentLength);
    printf(" System Type is %s ",szFileSystemNameBuffer);
    if (dwFileSystemFlags & FILE_SUPPORTS_REPARSE_POINTS)
    {
    printf("The file system does not support volume mount points. ");
    }
    if (dwFileSystemFlags & FILE_VOLUME_QUOTAS)
    {
    printf("The file system supports disk quotas. ");
    }
    if (dwFileSystemFlags & FILE_CASE_SENSITIVE_SEARCH)
    {
    printf("The file system supports case-sensitive file names. ");
    }
    printf("... ");
    return TRUE;
    }

  • 相关阅读:
    HDU 1213 How Many Tables(并查集,简单)
    POJ 1611 The Suspects(并查集,简单)
    HDU 4539 郑厂长系列故事――排兵布阵(曼哈顿距离)
    POJ 2411 Mondriaan'sDream(状压DP)
    ZOJ 4257 MostPowerful(状压DP,简单)
    HDU 3001 Traveling(状压DP)
    POJ 3311 Hie with the Pie(Floyd+状态压缩DP)
    POJ 1185 炮兵阵地(状态压缩DP)
    POJ 3254 Corn Fields(状态压缩DP)
    XueXX and Chessboard(dp)
  • 原文地址:https://www.cnblogs.com/kex1n/p/5545741.html
Copyright © 2011-2022 走看看