FindFirstVolume系列函数遍历驱动器,获取驱动器信息
什么是“卷”?
卷,又稱為“邏輯驅(qū)動器”,是 NTFS, FAT32 等文件系統(tǒng)組織結(jié)構(gòu)的最高層。卷是存儲設(shè)備(如硬盤)上由文件系統(tǒng)管理的一塊區(qū)域,是在邏輯上相互隔離的存儲單元。一個磁盤分區(qū)至少包含一個卷,當然卷也可以存在于多個磁盤分區(qū)上,僅存在于一個分區(qū)上的卷稱為“簡單卷“,存在于多個磁盤分區(qū)上的卷稱為”多分區(qū)卷“或”跨區(qū)卷“。最為常見的情況是一個分區(qū)只包含 一個卷,一個卷只存在于一個分區(qū)上,所以往往會造成的混淆是卷等于分區(qū)。卷存在卷標,程序可以通過卷標訪問卷。
?
卷掛接在 Unix/Linux/Netware 系統(tǒng)上應用比較常見,Windows 可能由于多用于個人平臺,所以知道卷掛接技術(shù)的人就比例上來說少了很多。你可以將它理解為:把一個物理設(shè)備掛接到一個邏輯盤符或文件夾中來使用,例如:如果需要擴展 C 盤的容量,而 C 盤所在的分區(qū)/磁盤已沒有空閑空間來擴展它時,可以加裝一個 200GB 的新硬盤,然后在 C: 中新增一個目錄 ExtDisk,并將這個新磁盤掛接到這個目錄中即可,現(xiàn)在 C: 盤的容量就增加了 200GB。有一點要注意,就是卷掛接只能用于 NTFS 系統(tǒng)。
?
4.2.1 遍歷卷并獲取屬性
獲取一個主機上的所有驅(qū)動器列表有兩種方法,一種是使用 GetLogicalDrives 或
GetLogicalDriveStrings,另一種是使用 FindFirstVolume 和 FindNextVolume 組合。
第一種方法獲取主機上的邏輯驅(qū)動器,也就是所有分配的卷標的驅(qū)動器,返回的結(jié)果是
驅(qū)動器的根路徑。第二種方法返回的是“\\?\volume{GUID}”形式的驅(qū)動器設(shè)備名。
使用 GetDriveType API 可以獲取驅(qū)動器類型,使用 GetVolumeInformation 可以獲取驅(qū)
動器屬性。
1.關(guān)鍵 API
(1) GetLogicalDrives。
獲取主機中所有的邏輯驅(qū)動器,以 BitMap 的形式返回,其函數(shù)原型如下:
◇返回值
GetLogicalDrive 函數(shù)返回一個 DWORD 類型的值,第一位表示所對應的驅(qū)動器是否存在。
一般情況下 DWORD 的數(shù)據(jù)長度是 32 位,在這個 DWORD 中,每一位對應了一個邏輯驅(qū)動器是
否存在。第二位如果是“1”則表示驅(qū)動器“B:”存在,第 4 位如果是“1”則表示驅(qū)動器
“D:”是存在的,以此類推。
(2) GetLogicalDriverStrings。
獲取主機中所有驅(qū)動器,以驅(qū)動器根路徑字符串返回,其函數(shù)原型如下:
◇參數(shù)
nBufferLength:參數(shù) lpBuffer 所指向的內(nèi)存空間的大小,以字節(jié)為單位。
lpBuffer:指向存儲返回結(jié)果字符串的內(nèi)存空間。
◇返回值
函數(shù)的返回值指明了函數(shù)調(diào)用是否成功,如果成功則返回緩沖區(qū)中返回結(jié)果的總長度。
如果返回值大于 nBufferLength,說明給定的緩沖區(qū)大小不夠,返回值是實際需要的大小。
如果返回 0,則說明函數(shù)運行出錯。
◇使用說明
這個 API 實現(xiàn)了與 GetLogicalDrives 同樣的功能,卻以一種更直觀的方式返回執(zhí)行結(jié)
果。函數(shù)執(zhí)行結(jié)果放在 lpBuffer 所指向的內(nèi)存區(qū)域中,此內(nèi)存區(qū)域大小由 nBufferLength
參數(shù)指定,使函數(shù)返回結(jié)果不至于溢出。在調(diào)用此函數(shù)前需保證內(nèi)存分配。
函數(shù)調(diào)用成功后,將在緩沖區(qū)中依次填入本機所具有的驅(qū)動器根路徑字符串,如在筆者
系統(tǒng)中有 5 個邏輯驅(qū)動器“C:\”、“D:\”“E:\”、“F:\”、“I:\”。執(zhí)行后在緩沖
區(qū)中的結(jié)果如下:
也就是連續(xù)放置了“C:\”、“D:\”“E:\”、“F:\”、“I:\”這 5 個字符串(會
在每個字符串后加一個‘\o’結(jié)束符,在所有卷標字符串的最后再加一個結(jié)束符)。
(3)FindFirstVolume。
查找主機中的第一個驅(qū)動器,返回驅(qū)動器設(shè)備名,其函數(shù)原型如下:
◇參數(shù)
lpszVolumeName:指向驅(qū)動器名的內(nèi)存緩沖區(qū)。
cchBufferLength:參數(shù) lpszVolumeName 所指向的緩沖區(qū)大小,以字節(jié)為單位。
◇返回值
驅(qū)動器查找句柄, F 貓 NextVolume 和 FindVolumeColse 的參數(shù), 如果執(zhí)行失敗, 返回 NULL。
(4)FindNextVolume
查找主機中后繼的邏輯驅(qū)動器,其函數(shù)原型如下:
◇參數(shù)
hFindVolume: FindFirstVolume 所返回的驅(qū)動器查找句柄。
lpszVolumeName:指向保存驅(qū)動器名的內(nèi)存緩沖區(qū)。
cchBufferLength:參數(shù) lpszVolumeName 所指向的緩沖區(qū)大小,以字節(jié)為單位。
◇返回值
返回 BOOL 表示是否成功,如果失敗說明已經(jīng)查找完成所有邏輯驅(qū)動器。
(5)FindVo1umeClose。
\關(guān)閉 FindFirstVolume 打開的卷遍歷句柄,其函數(shù)原型如下:
◇參數(shù)
hFindVolume:要關(guān)閉的驅(qū)動器查找句柄。
◇返回值
返回 BOOL 值表示是否成功關(guān)閉句柄。
(6) GetDriveType。
獲取驅(qū)動器類型,其函數(shù)原型如下:
◇參數(shù)
lpRootPathIName:驅(qū)動器根路徑,如“C:\”。
◇返回值 /
驅(qū)動器的類型,如 DRIVE' FIXED 表示硬盤,DRIVE_CDROM 表示光盤等。詳見實例 4-2
的 GetDirverInfo 函數(shù)。
(7) GetVolumeInformation。
獲取邏輯驅(qū)動器信息,其函數(shù)原型如下:
◇參數(shù)
lpRootPathName:輸入?yún)?shù),指向所要獲取屬性的驅(qū)動器的根路徑字符串。
lpVolumeNameBuffer:輸出參數(shù),返回驅(qū)動器名。
?
GetLogicalDriveStrings枚舉磁盤,然后可以調(diào)用GetDiskFreeSpaceEx獲取大小信息。
?
?
GetLogicalDrives
DWORD WINAPI GetLogicalDrives(void);
該函數(shù)沒有參數(shù),返回值為DWORD,是一個位掩碼代表當前的磁盤驅(qū)動器。第0位表示驅(qū)動器A,第二位表示驅(qū)動器B。以此類推,某一位為1表示存在驅(qū)動器,為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 ,存儲驅(qū)動器根路徑字符串的緩沖區(qū)內(nèi)存 nBufferLength 緩沖區(qū) 的大小 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, //驅(qū)動器名的緩沖區(qū)_In_???DWORD cchBufferLength //緩沖區(qū)的大小
);
返回值為驅(qū)動器的句柄 該函數(shù)用來查找主機上第一個驅(qū)動器,返回驅(qū)動器名。 ? BOOL WINAPI FindNextVolume(_In_???HANDLE hFindVolume, //調(diào)用FindFirstVolume返回的驅(qū)動器句柄_Out_??LPTSTR lpszVolumeName, //驅(qū)動器名的緩沖區(qū)_In_???DWORD cchBufferLength //緩沖區(qū)的大小
);
查找下一個驅(qū)動器 ? BOOL WINAPI FindVolumeClose(_In_??HANDLE hFindVolume //調(diào)用FindFirstVolume返回的驅(qū)動器句柄);
該函數(shù)用來關(guān)閉一個驅(qū)動器的句柄。被關(guān)閉的句柄就不能再在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)
* 功能:查找主機中的第一個驅(qū)動器
* 參數(shù):buf,BUFSIZE
* buf 指向驅(qū)動器名的內(nèi)存緩存區(qū)
* BUFSIZE 參數(shù)buf所指向的緩存區(qū)大小
* 返回值 HANDLE :驅(qū)動器設(shè)備名
**********************************/
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函數(shù)
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);
* 功能:判斷一個磁盤驅(qū)動器的類型
* 參數(shù):LPSTR szDrive?
* 指明要獲取屬性的驅(qū)動器的根目錄,如C:\
* 返回值 UINT:表示磁盤類型
**********************/
uDiveType = GetDriveType(szDrive);
switch(uDiveType)
{
case DRIVE_UNKNOWN://未知磁盤類型
printf("The drive type cannot be determined.");
break;
case DRIVE_NO_ROOT_DIR://說明參數(shù)是無效
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://網(wǎng)絡(luò)磁盤
printf("The drive is a remote (network) drive");
break;
case DRIVE_CDROM://光驅(qū)
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)
* 功能:獲取磁盤驅(qū)動器的信息
* 參數(shù):如下
* 返回值:非零即成功
***********************************/
if (!GetVolumeInformation(szDrive,
szDirverName,//卷標(字符串)
MAX_PATH,//szDirveName的長度
&dwVolumeSerialNumber,//用于裝載磁盤卷序列號的變量
&dwMaximumComponentLength,//用于裝載文件名每一部分的長度
&dwFileSystemFlags,//用于裝載一個或多個二進制位標志的變量
szFileSystemNameBuffer,//系統(tǒng)類型
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;
}
總結(jié)
以上是生活随笔為你收集整理的FindFirstVolume系列函数遍历驱动器,获取驱动器信息的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C#2.0 从sql server 中读
- 下一篇: MDK4 如何生成bin文件