Win32文件系统编程

            Win32文件系统编程

一丶了解什么是文件系统

  文件系统是抽象的.是windows在软件层面提供的一层虚拟的数据结构.编程

文件系统分为NTFS 跟 FAT32. 具体看看二者的区别吧.windows

磁盘分区容量. api

单个文件容量.  意思就是一个文件能够是多大的. NTFS 是能够4G以上的大文件. FAT32则不能够.缓存

EFS加密.  这个加密主要针对当前用户的(例如Admins 管理员帐户)  具体能够 点击一个文件. 文件->属性 -> 高级 -> 加密保护文件内容.安全

若是在当前用户则不会有什么结果. 可是若是换了用户访问.则不能够访问这个加密文件了.数据结构

加密后的文件.app

文件颜色都会改变.异步

 

磁盘配额  意思就是能够限制别的用户访问这个硬盘多少G内存. 函数

具体设置 xp下  盘符属性-> 配额 学习

关于上面的讲解咱们只须要了解便可.不深究.具体的的是学习API. API为咱们封装好了.咱们并不用关心NTFS 或者FAT32

 

二丶Windows提供的操做 "文件" 的 API

   标题中文件为何添加了引号. 意思是不光能够操做文件. 在windows系统中.一切东西都虚拟为了文件. 例如管道 等等.. 均可以使用这些API.

api具体介绍

1.了解卷 文件 跟目录的关系. 卷API

 卷指的就是咱们的的逻辑硬盘. 例如C盘.

 目录则是C盘里面的文件夹. 文件夹里面可能仍是以文件夹. 也多是文件.

卷操做API 很简单. 经常使用的就四个.

DWORD GetLogIcalDrives()  获取卷    返回值是10进制.咱们须要转化成16进制.而后转换成二进制查看.每一位为1表明有这个磁盘.不然则没有

GetLogIcalDriveStrings(buffsize,buf) 获取一个卷的盘符的字符串 

GetDriveType(""目录名称") 获取卷的类型

GetVolumeInformation() 获取卷的类型

如如下代码例子:

  

// A.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <Windows.h>

int main()
{
    //1.获取磁盘逻辑驱动卷
    DWORD dwGetDrives = GetLogicalDrives();
    /*
    例如个人返回值是 252 
    转化为16进制  FC
    转化为二进制 11111100   表明咱们有六个磁盘.
    CDEFGH  而个人刚好就是 CDEFGH 盘.
    */

    //2.获取磁盘卷字符串.
    TCHAR wszBuf[1024] = { NULL };
    DWORD dwSize = sizeof(TCHAR) * 1024;
    GetLogicalDriveStringsW(dwSize, wszBuf);  
    /*
        逻辑驱动器返回后会存在wszBuf里面. 本身作分割便可.
        例如 C:\ B:\
    */

    //3.根据指定盘符获取它的类型. 能够移除的仍是不能够移除的.
    DWORD dwDriveType = GetDriveTypeW(TEXT("C:\\")); //具体返回值查询MSDN 注意从0开始

    //4.获取卷的详细信息.
    DWORD dwVolumneSerial = 0;   //驱动卷的序列号(不是硬盘序列号)
    DWORD dwFileMaxLen = 0;      //系统容许的最大文件名的长度
    DWORD dwFileSystem = 0;      //文件系统标识.
    TCHAR dwFileSystemBuffer[255] = { 0 };  //文件操做系统的名称
    
    TCHAR szVolName[255] = { 0 }; //返回的卷的别名
    GetVolumeInformationW(
        TEXT("c:\\"),        // IN参数 你要查看那个卷的信息
        szVolName,             // OUT参数. 查询到的卷的别名会给你.例如你的别名是C
        sizeof(TCHAR) * 255, // IN参数. 上面缓冲区的大小.
        &dwVolumneSerial,    // OUT 驱动卷的序列号
        &dwFileMaxLen,      //  OUT 写文件读文件等等文件名最大能够是多大.
        &dwFileSystem,      //  OUT 文件操做系统标识.有多中宏组合,具体能够查询MSDN. 标识你这个文件是
        dwFileSystemBuffer, //你当前系统是 NTFS 仍是FAT32
        sizeof(TCHAR) * 255 //上面缓冲区的大小.
    );


    return 0;
}

2.文件夹(目录) 操做的相关API

  

CreateDirectory();//建立目录
RemoveDirectory();//删除目录
MoveFile(); //修改目录名称.
GetCurrentDirectory(); //获取进程当前目录
SetCurrentDirectory(); //设置进程当前目录.

具体代码例子:

    main函数调用便可.

void GetDirectoryApi()
{
    CreateDirectory(TEXT("D:\\123"),NULL);//建立目录
    MoveFile(TEXT("D:\\123"), TEXT("D:\\456"));          //修改目录名称.
    RemoveDirectory(TEXT("D:\\456"));//删除目录
    TCHAR szCurrentDirectoryBuffer[255] = { 0 };
    DWORD dwBuffsize = sizeof(TCHAR) * 255;

    GetCurrentDirectory(dwBuffsize, szCurrentDirectoryBuffer); //获取当前目录
    SetCurrentDirectory(szCurrentDirectoryBuffer); //设置当前目录.
}

3.文件操做相关API

CreateFile( ) 建立文件

DeleteFile();  删除文件

CloseHandle();  关闭文件句柄

GetFileSize();  获取文件大小.

ReadFile();    读文件

WriteFile();    写文件

CopyFile();   拷贝文件

  具体看以下代码详解参数意义.

  

void OptFileApi()
{
    //1.建立文件
    HANDLE hFile = CreateFile(
        TEXT("D:\\123.txt"),                //你要建立的文件名 
        GENERIC_READ | GENERIC_WRITE,      // 建立的这个文件只读模式建立时只写模式建立仍是读写均可以.若是只读则不能够写.
        0,                                   // 文件共享模式. 意思就是你这个文件建立完毕以后.当前读写只能有一我的在用,其余人不能操做. 为0就是排他. 或者说你能够设置为其余人能够读.
        NULL,                              //  每一个内核对象都有的SD安全属性
        OPEN_EXISTING,                     //建立文件的信息. 你这个文件是文件不存在就建立 仍是打开已经存在的. 仍是老是建立新的.
        FILE_ATTRIBUTE_NORMAL,              //建立的文件属性.  意思就是我建立的这个文件是隐藏文件啊 仍是别的文件. 反正就是属性.
        NULL
    );
    //2.获取文件大小
    DWORD dwLowSize = 0;
    DWORD dwHighSize = 0;
    dwLowSize = GetFileSize(hFile, &dwHighSize);  //若是是32位系统.返回值存储了大小.若是是64位系统.则高32位也会存储. 
    //3.写文件
    TCHAR szBuffer[1024] =TEXT("HelloFile");
    DWORD dwSize = sizeof(TCHAR) * 1024;
    DWORD OutSize = 0;
    WriteFile(hFile,        //往哪一个文件中写
        szBuffer,           //写入的Buffer数据
        dwSize,             //写入的大小
        &OutSize,           //实际写入的大小.操做系统返回给你
        NULL);              //异步操做不须要
    //4.读文件
    //4.1设置File读取位置
    SetFilePointer(hFile,  //读取那个文件
        1,                 //低32位的偏移.具体偏移 就是从文件开始位置 + 偏移位置读取. 若是是64位那么第三个参数也要使用.
        0,
        FILE_BEGIN         //偏移起始位置. 文件开始 文件结束. 仍是文件中间
    );
    ReadFile(hFile,            //读哪一个
        szBuffer,           //读入的数据放到Buffer
        dwSize,             //Buffer大小
        &OutSize,           //实际读入的大小.操做系统返回给你
        NULL);              //异步操做不须要

    CloseHandle(hFile);

    //5.拷贝文件
    CopyFile(
        TEXT("D:\\123.txt"),   //源文件
        TEXT("E:\\123.txt"),   //目的文件
        TRUE                  //是否覆盖目的文件
    );
    //.关闭文件句柄
    
    //6.删除文件
    DeleteFile(TEXT("d:\\123.txt"));

}

 三丶内存映射文件

  咱们上几篇博客讲解了CreateFileMaping 建立物理内存页. 那么咱们能够把文件跟物理页绑定.

例以下图:

  

其实文件映射到物理内存了.那么咱们直接操做内存就能够. 想至关于操做文件.

具体步骤.

  1.建立文件.若是文件已经存在.则打开文件.获取文件句柄.

  2.申请共享内存.使用CreateFileMapping. 将文件句柄传入.

  3,将物理内存映射到线性地址(虚拟内存)中.使用 MapViewOfFile.

  4.操做的虚拟地址就是文件内容了.

具体看以下代码.

  

void OptFileApi()
{
//1.建立文件
HANDLE hFile = CreateFile(
TEXT("D:\\calc.exe"), //你要建立的文件名 
GENERIC_READ | GENERIC_WRITE, // 建立的这个文件只读模式建立时只写模式建立仍是读写均可以.若是只读则不能够写.
0, // 文件共享模式. 意思就是你这个文件建立完毕以后.当前读写只能有一我的在用,其余人不能操做. 为0就是排他. 或者说你能够设置为其余人能够读.
NULL, // 每一个内核对象都有的SD安全属性
OPEN_EXISTING, //建立文件的信息. 你这个文件是文件不存在就建立 仍是打开已经存在的. 仍是老是建立新的.
FILE_ATTRIBUTE_NORMAL, //建立的文件属性. 意思就是我建立的这个文件是隐藏文件啊 仍是别的文件. 反正就是属性.
NULL
);

//2.建立内存物理页.跟文件挂靠
HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE,0, 0X1000, NULL); //读写的方式映射.不须要其它进程使用.


//3.映射到虚拟内存位置.
LPVOID szBuffer = MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);

//直接操做内存便可.
printf("%x",*(PDWORD)szBuffer); //打印前四个字节.
*(PDWORD)szBuffer = 0xFFFF0000; //修改文件前四个字节.
/*
此API能够 强制更新缓存.
BOOL FlushViewOfFile( LPCVOID lpBaseAddress, // starting address
SIZE_T dwNumberOfBytesToFlush // number of bytes in range);
*/
//4.取消映射
UnmapViewOfFile(szBuffer);
CloseHandle(hFileMap);
CloseHandle(hFile);

}

  

 

若是映射到虚拟内存中.也就是调用完毕 MapViewOfFile的时候.其缓冲区就是文件的起始位置. 能够直接指针修改了.

例如咱们的Calc计算器.头四个字节已经被咱们修改为了 0xFFFF了.

 

 很简单. 多动手作便可.

 四丶内存映射文件之多进程共享.

  以下图所示:

  

A进程映射物理内存.而且映射文件. B进程使用这块物理内存其实也是操做文件.

只不过附带了一个文件.修改修改物理内存的时候变成修改文件了.具体代码不在贴了.

主须要申请共享内存的时候给定一个名字. 那么双进程就可使用了.

 

完整代码    

BOOL Characteristic(LPCTSTR lpFileName)
{
    //打开文件,读取头八个字节.
    HANDLE hFile = CreateFile(
        lpFileName,
        GENERIC_READ | GENERIC_WRITE,      
        0,                                 
        NULL,                             
        OPEN_EXISTING,                     
        FILE_ATTRIBUTE_NORMAL,          
        NULL
    );

    if (INVALID_HANDLE_VALUE == hFile)
        return FALSE;

    //读取文件特征.这里判断是不是PE.读取节个数.以及节开头的标志.

    
    HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0X1000, NULL); 
    if (NULL == hFileMap)
        return FALSE;
    
    LPVOID szBuffer = MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
    if (NULL == szBuffer)
        return FALSE;
    
    UnmapViewOfFile(szBuffer);
    CloseHandle(hFileMap);
    CloseHandle(hFile);
    return 0;
}
相关文章
相关标签/搜索