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()\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系列函数遍历驱动器,获取驱动器信息的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C#2.0 从sql server 中读
- 下一篇: MDK4 如何生成bin文件