《Windows核心编程》---逻辑驱动器操作

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, //用于接收文件系统字符串,函数在这里返回类似于

                                                        //FATFAT32NTFS类型的字符串

  __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 );

}

posted on 2010-07-26 10:56  android开发实例  阅读(949)  评论(0编辑  收藏  举报

导航