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;
}
相關文章
相關標籤/搜索