Windows中的文件组织方式采用分层次的结构:计算机中可以安装有多个物理驱动器,每个物理驱动器可以分为多个主分区和扩展分区,每个主分区就是一个逻辑驱动器,而每个扩展分区可以划分为多个逻辑驱动器,逻辑驱动器组成我们熟悉的C盘与D盘等盘符。
对于每个逻辑驱动器,可以给它取一个标号叫做“卷标”,卷标是当作一个目录项存放在逻辑驱动器的根目录中的。
逻辑驱动器操作:
SetVolumeLabel函数用来为一个驱动器创建、修改以及删除卷标:
BOOL WINAPI SetVolumeLabel(
__in_opt LPCTSTR lpRootPathName, //要设置卷标的逻辑驱动器根目录,如“c:/”
__in_opt LPCTSTR lpVolumeName //指向包含卷标字符串的缓冲区
);
要检测系统中当前存在多少个逻辑驱动器可以使用GetLogicalDrives函数,函数返回所有可用的盘符:
DWORD WINAPI GetLogicalDrives(void);
函数返回一个32位整数,用其中的每一位代表是否存在一个逻辑驱动器。由于系统中可用的盘符仅有26个(A:~Z:),所以32位已经可以反映出所有的逻辑驱动器,以及它们的盘符分布情况了。返回值的第0位到第25位分别代表驱动器A:~Z:是否存在。
函数GetLogicalDriveStrings返回字符串类型的逻辑驱动器列表:
DWORD WINAPI GetLogicalDriveStrings(
__in DWORD nBufferLength, //缓冲区大小,如果缓冲区不够大,后面的数据会被截断
__out LPTSTR lpBuffer //指向一个缓冲区,函数在这里返回"A:/", 0, "B:/", 0,"C:/", 0, 0
//格式的字符串,字符串列表以一个附加的0结束
);
函数GetDriveType用来检测驱动器类型:
UINT WINAPI GetDriveType(
__in_opt LPCTSTR lpRootPathName //指向存放有逻辑驱动器根目录的字符串的缓冲区
);
函数返回值是逻辑驱动器的类型:
0 //驱动器类型无法检测
1 //指定的根目录不存在
DRIVE_REMOVABLE //可移动介质,如软盘
DRIVE_FIXED // 固定盘,如硬盘中的逻辑驱动器
DRIVE_REMOTE //远程驱动器,如网络上映射的驱动器
DRIVE_CDROM //光盘
DRIVE_RAMDISK //内存虚拟盘
函数GetVolumeInformation用来获得逻辑驱动器的卷标、序列号和文件系统类型等属性:
BOOL WINAPI GetVolumeInformation(
__in_opt LPCTSTR lpRootPathName, //指向需要检测的驱动器根目录字符串,如果要检测的是网络
//上的驱动器,字符串的格式是:“//服务器名//共享名”
__out LPTSTR lpVolumeNameBuffer, //指向返回驱动器的卷标的缓冲区
__in DWORD nVolumeNameSize, //上述缓冲区大小
__out_opt LPDWORD lpVolumeSerialNumber, //指向返回逻辑驱动器序列号的缓冲区
//序列号是驱动器被格式化时由系统随机生成的一个32位数,它保存于驱动器第一个扇区
//的引导记录中
__out_opt LPDWORD lpMaximumComponentLength, //指向返回最大允许的文件名长度的缓冲区,
//在Windows系统中,一般这个数值是255
__out_opt LPDWORD lpFileSystemFlags, //返回逻辑驱动器的属性标记…
__out LPTSTR lpFileSystemNameBuffer, //用于接收文件系统字符串,函数在这里返回类似于
//FAT、FAT32、NTFS类型的字符串
__in DWORD nFileSystemNameSize //上述缓冲区大小
);
GetDiskFreeSpace函数用来检测逻辑驱动器剩余空间:
BOOL WINAPI GetDiskFreeSpace(
__in LPCTSTR lpRootPathName, //指向需要检测的驱动器根目录字符串
__out LPDWORD lpSectorsPerCluster, //返回每簇扇区数
__out LPDWORD lpBytesPerSector, //返回每扇区字节数
__out LPDWORD lpNumberOfFreeClusters, //返回驱动器中未使用的簇的数量
__out LPDWORD lpTotalNumberOfClusters //返回驱动器中簇的总数
);
下面的实例代码演示了从一个文件句柄获得文件名字,使用到了GetLogicalDriveStrings函数:
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <string.h>
#include <psapi.h>
#include <strsafe.h>
#define BUFSIZE 512
BOOL GetFileNameFromHandle(HANDLE hFile)
{
BOOL bSuccess = FALSE;
TCHAR pszFilename[MAX_PATH+1];
HANDLE hFileMap;
// Get the file size.
DWORD dwFileSizeHi = 0;
DWORD dwFileSizeLo = GetFileSize(hFile, &dwFileSizeHi);
if( dwFileSizeLo == 0 && dwFileSizeHi == 0 )
{
printf("Cannot map a file with a length of zero./n");
return FALSE;
}
// Create a file mapping object.
hFileMap = CreateFileMapping(hFile,
NULL,
PAGE_READONLY,
0,
1,
NULL);
if (hFileMap)
{
// Create a file mapping to get the file name.
void* pMem = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 1);
if (pMem)
{
if (GetMappedFileName (GetCurrentProcess(),
pMem,
pszFilename,
MAX_PATH))
{
// Translate path with device name to drive letters.
TCHAR szTemp[BUFSIZE];
szTemp[0] = '/0';
if (GetLogicalDriveStrings(BUFSIZE-1, szTemp))
{
TCHAR szName[MAX_PATH];
TCHAR szDrive[3] = TEXT(" :");
BOOL bFound = FALSE;
TCHAR* p = szTemp;
do
{
// Copy the drive letter to the template string
*szDrive = *p;
// Look up each device name
if (QueryDosDevice(szDrive, szName, MAX_PATH))
{
UINT uNameLen = _tcslen(szName);
if (uNameLen < MAX_PATH)
{
bFound = _tcsnicmp(pszFilename, szName, uNameLen) == 0;
if (bFound && *(pszFilename + uNameLen) == _T('//'))
{
// Reconstruct pszFilename using szTempFile
// Replace device path with DOS path
TCHAR szTempFile[MAX_PATH];
StringCchPrintf(szTempFile,
MAX_PATH,
TEXT("%s%s"),
szDrive,
pszFilename+uNameLen);
StringCchCopyN(pszFilename, MAX_PATH+1, szTempFile, _tcslen(szTempFile));
}
}
}
// Go to the next NULL character.
while (*p++);
} while (!bFound && *p); // end of string
}
}
bSuccess = TRUE;
UnmapViewOfFile(pMem);
}
CloseHandle(hFileMap);
}
_tprintf(TEXT("File name is %s/n"), pszFilename);
return(bSuccess);
}
int _tmain(int argc, TCHAR *argv[])
{
HANDLE hFile;
if( argc != 2 )
{
printf("This sample takes a file name as a parameter./n");
return 0;
}
hFile = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, 0, NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
printf("CreateFile failed with %d/n", GetLastError());
return 0;
}
GetFileNameFromHandle( hFile );
}