Win32文件系统编程

一丶了解什么是文件系统

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

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

磁盘分区容量.

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

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

如果在当前用户则不会有什么结果. 但是如果换了用户访问.则不可以访问这个加密文件了.

加密后的文件.

文件颜色都会改变.

磁盘配额  意思就是可以限制别的用户访问这个硬盘多少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[] = { NULL };
DWORD dwSize = sizeof(TCHAR) * ;
GetLogicalDriveStringsW(dwSize, wszBuf);
/*
逻辑驱动器返回后会存在wszBuf里面. 自己做分割即可.
例如 C:\ B:\
*/ //3.根据指定盘符获取它的类型. 可以移除的还是不可以移除的.
DWORD dwDriveType = GetDriveTypeW(TEXT("C:\\")); //具体返回值查询MSDN 注意从0开始 //4.获取卷的详细信息.
DWORD dwVolumneSerial = ; //驱动卷的序列号(不是硬盘序列号)
DWORD dwFileMaxLen = ; //系统允许的最大文件名的长度
DWORD dwFileSystem = ; //文件系统标识.
TCHAR dwFileSystemBuffer[] = { }; //文件操作系统的名称 TCHAR szVolName[] = { }; //返回的卷的别名
GetVolumeInformationW(
TEXT("c:\\"), // IN参数 你要查看那个卷的信息
szVolName, // OUT参数. 查询到的卷的别名会给你.例如你的别名是C
sizeof(TCHAR) * , // IN参数. 上面缓冲区的大小.
&dwVolumneSerial, // OUT 驱动卷的序列号
&dwFileMaxLen, // OUT 写文件读文件等等文件名最大可以是多大.
&dwFileSystem, // OUT 文件操作系统标识.有多中宏组合,具体可以查询MSDN. 标识你这个文件是
dwFileSystemBuffer, //你当前系统是 NTFS 还是FAT32
sizeof(TCHAR) * //上面缓冲区的大小.
); return ;
}

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[] = { };
DWORD dwBuffsize = sizeof(TCHAR) * ; 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就是排他. 或者说你可以设置为其他人可以读.
NULL, // 每个内核对象都有的SD安全属性
OPEN_EXISTING, //创建文件的信息. 你这个文件是文件不存在就创建 还是打开已经存在的. 还是总是创建新的.
FILE_ATTRIBUTE_NORMAL, //创建的文件属性. 意思就是我创建的这个文件是隐藏文件啊 还是别的文件. 反正就是属性.
NULL
);
//2.获取文件大小
DWORD dwLowSize = ;
DWORD dwHighSize = ;
dwLowSize = GetFileSize(hFile, &dwHighSize); //如果是32位系统.返回值存储了大小.如果是64位系统.则高32位也会存储.
//3.写文件
TCHAR szBuffer[] =TEXT("HelloFile");
DWORD dwSize = sizeof(TCHAR) * ;
DWORD OutSize = ;
WriteFile(hFile, //往哪个文件中写
szBuffer, //写入的Buffer数据
dwSize, //写入的大小
&OutSize, //实际写入的大小.操作系统返回给你
NULL); //异步操作不需要
//4.读文件
//4.1设置File读取位置
SetFilePointer(hFile, //读取那个文件
, //低32位的偏移.具体偏移 就是从文件开始位置 + 偏移位置读取. 如果是64位那么第三个参数也要使用.
,
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,
,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
); if (INVALID_HANDLE_VALUE == hFile)
return FALSE; //读取文件特征.这里判断是否是PE.读取节个数.以及节开头的标志. HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, , 0X1000, NULL);
if (NULL == hFileMap)
return FALSE; LPVOID szBuffer = MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, , , );
if (NULL == szBuffer)
return FALSE; UnmapViewOfFile(szBuffer);
CloseHandle(hFileMap);
CloseHandle(hFile);
return ;
}

Win32文件系统编程的更多相关文章

  1. Win32 OpenGL 编程( 1 ) Win32 下的 OpenGL 编程必须步骤

    http://blog.csdn.net/vagrxie/article/details/4602961 Win32 OpenGL 编程( 1 ) Win32 下的 OpenGL 编程必须步骤 wri ...

  2. win32 C++制作美观按钮,告别win32 API编程中默认的灰色按钮

    使用win32 API制作美观按钮,当鼠标移入/移出按钮时改变按钮背景颜色,类似HTML网页中的效果,告别win32 API编程中默认的灰色按钮,效果图见下面动图和视频. 下载地址: 按钮效果(win ...

  3. Win32多线程编程(1) — 基础概念篇

      内核对象的基本概念 Windows系统是非开源的,它提供给我们的接口是用户模式的,即User-Mode API.当我们调用某个API时,需要从用户模式切换到内核模式的I/O System Serv ...

  4. Win32多线程编程(2) — 线程控制

    Win32线程控制只有是围绕线程这一内核对象的创建.挂起.恢复.终结以及通信等操作,这些操作都依赖于Win32操作系统提供的一组API和具体编译器的C运行时库函数.本篇围绕这些操作接口介绍在Windo ...

  5. Win32多线程编程(3) — 线程同步与通信

      一.线程间数据通信 系统从进程的地址空间中分配内存给线程栈使用.新线程与创建它的线程在相同的进程上下文中运行.因此,新线程可以访问进程内核对象的所有句柄.进程中的所有内存以及同一个进程中其他所有线 ...

  6. win32多线程编程

    关于多线程多进程的学习,有没有好的书籍我接触的书里头关于多线程多进程部分,一是<操作系统原理>里面讲的相关概念   一个是<linux基础教程>里面讲的很简单的多线程多进程编程 ...

  7. win32串口编程

    翻译自:ms-help://MS.MSDNQTR.v80.chs/MS.MSDN.v80/MS.WIN32COM.v10.en/dnfiles/html/msdn_serial.htm 老外写的文章, ...

  8. pthread Win32多线程编程的一些知识和感想

    研究遗传算法的一大诟病就是每次运行程序的结果并不是完全一样的,有时候能找到最优解有时候找不到最优解,这就是遗传算法的概率性导致的.那么怎么评价你的方法的好坏呐,这时候就要多次独立运行程序最后取结果的平 ...

  9. Win32 API编程——前言

    一丶什么是Win32 API? 微软为了保护操作系统的安全性和稳定性,把系统分为内核层和用户层(内核层的代码只能在当CPU的特权级为R0状态下执行,用户层的代码在CPU特权级为R0和R3都能执行),w ...

随机推荐

  1. 2019.03.09 codeforces620E. New Year Tree(线段树+状态压缩)

    传送门 题意:给一棵带颜色的树,可以给子树染色或者问子树里有几种不同的颜色,颜色值不超过606060. 思路:颜色值很小,因此状压一个区间里的颜色用线段树取并集即可. 代码: #include< ...

  2. 连接EMC存储系统

    1.准备一台笔记本电脑,一根网线即可. 2.将网线一头连接笔记本电脑,另一头连接存储.(连接存储的一头应连接到有扳手图标的那一网口上) 3.配置IP地址 IP:128.221.1.254 子网掩码:2 ...

  3. linux下PythonQt混编记录

    看了很多博主经验,然后自己实验总结出来的,就不一一写出处了,非常感谢各位博主的分享经验. 一.安装Python3.6 安装依赖环境 # yum -y install zlib-devel bzip2- ...

  4. django 如何接收bootstrap-table传送的 ajax数组

    今天在用django传递id的时候,使用 alert(ids)以及console.log("id:",ids),都可以看到是把选中的数据的id打印出来的,用console.log可 ...

  5. sudo -iu [用户] 命令无法正常切换到用户目录的原因

    今天干活时遇到一个问题,在sudo -iu [用户]命令执行后无法切换到用户对应的[ 用户@机器 ~$ ]命令行 .bashrc已正常配置为 if [ -f /etc/bashrc ]; then . ...

  6. Layui++>>ajax传递数组,防止深度序列化

  7. 【python-appium】appium 关键字

    Appium 服务关键字 关键字 描述 实例 automationName 你想使用的自动化测试引擎 Appium (默认) 或 Selendroid platformName 你要测试的手机操作系统 ...

  8. python猜数字游戏console版本

    加入python学习小组后的第一次作业,python GUI写猜数字游戏.由于加班比较多,第一步先实现console版本,下一步再实现GUI版本. 虽然猜数字游戏是个小游戏,但是涉及到的基础知识点还是 ...

  9. 服务器windows2008系统登录报错:由于远程桌面服务当前正忙,因此无法完成您尝试的任务。请在...

    1.问题描述:windows server 2008服务器通过远程桌面登录时很慢,登录不进去,把远程桌面关掉后,再用远程桌面登录时,出现下图提示. 把服务器接上显示器键盘鼠标后,卡在系统登录的欢迎界面 ...

  10. UML顺序图知识点介绍(Sequence Diagram)

    消息 调用消息 调用(procedure call)消息的发送者把控制传递给消息的接收者,然后停止活动,等待消息接受者放弃会返回控制 在Rational Rose(2016版本如图所示) 异步消息 异 ...