在映射文件上调用 VirtualProtect
Posted
技术标签:
【中文标题】在映射文件上调用 VirtualProtect【英文标题】:Calling VirtualProtect on a mapped file 【发布时间】:2011-03-18 00:49:08 【问题描述】:我正在使用 CreateFileMapping 和 MapViewOfFile 函数将文件映射到内存中。在某一点之后,我调用 VirtualProtect 将其保护从只读更改为读写。此调用失败,GetLastError 给出 ERROR_INVALID_PARAMETER。
这是我演示问题的代码的简化版本。
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int main()
HANDLE fd, md;
char *addr;
DWORD old;
BOOL ok;
fd = CreateFile("filename", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
md = CreateFileMapping(fd, NULL, PAGE_READWRITE, 0, 100, NULL);
addr = MapViewOfFile(md, FILE_MAP_READ, 0, 0, 100);
ok = VirtualProtect(addr, 100, PAGE_READWRITE, &old);
if (!ok)
// we fall into this if block
DWORD err = GetLastError();
// this outputs "error protecting: 87"
printf("error protecting: %u\n", err);
return 1;
UnmapViewOfFile(addr);
CloseHandle(md);
CloseHandle(fd);
return 0;
我在这里做错了什么?我是否不允许在包含映射文件的区域上调用 VirtualProtect?
【问题讨论】:
之前的函数是否返回了预期值?我意识到您只发布了一个 sn-p ...但请确保您测试来自 MapViewOfFile、CreateFileMapping、CreateFile、...的 ALL 返回值... 是的,我确信其他功能没有失败。为简单起见,我省略了其他错误检查。 【参考方案1】:首先使用 FILE_MAP_READ | 创建视图FILE_MAP_WRITE 并使用 PAGE_READONLY 进行保护。现在您可以轻松地稍后将其设为 PAGE_READWRITE:
addr = MapViewOfFile(md, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 100);
ok = VirtualProtect(addr, 100, PAGE_READONLY, &old);
//...
ok = VirtualProtect(addr, 100, PAGE_READWRITE, &old);
【讨论】:
好的,所以我想以将来可能需要的最大访问权限调用 CreateFileMapping 和 MapViewOfFile。我要补充一点:如果我不是最初打开文件句柄的人,有没有办法找出该文件句柄上可用的最高访问级别? A FALSE return 和 GetLastError() 告诉你,同样的想法。 您是否建议我先尝试最高访问权限,然后再降低到不会给我错误的最低访问权限?我想这可能行得通,但似乎应该有更好的方法。 另外,在hostile environment
:-) - 在尝试 VirtualProtect 之前,您可以调用 VirtualQuery 并查看原始内存保护选项(MEMORY_BASIC_INFORMATION 结构的 AllocationProtect 成员)【参考方案2】:
在您的代码中发生的情况是 VirtualProtectEx
(由您的 VirtualProtect
调用)失败并出现错误 STATUS_SECTION_PROTECTION (0xC000004E) - “一个部分的视图指定了一个保护与初始视图的保护不兼容”,这似乎是您通过创建具有更多限制性保护 (FILE_MAP_READ) 的剖面视图所做的事情。
这个话题似乎没有足够的细节记录,所以我认为你最好按照汉斯的建议去做。
【讨论】:
【参考方案3】:根据http://msdn.microsoft.com/en-us/library/aa366556(v=vs.85).aspx,这应该是合法的。根据 VirtualProtect 文档,新标志必须与“VirtualAlloc”标志兼容——如果这转移到“MapViewOfFile”标志,我怀疑你可以加强但不能放松保护。尝试将读写映射并将保护更改为只读。
【讨论】:
以上是关于在映射文件上调用 VirtualProtect的主要内容,如果未能解决你的问题,请参考以下文章
什么时候在ARM板上安装操作系统?调用端口的地址会映射到真实地址还是虚拟地址?
RestKit 对象映射 POST 响应,“CoreData:错误:在 NSManagedObject 类映射操作上调用指定初始化程序失败”