什么时候出现错误1224:ERROR_USER_MAPPED_FILE?
When error 1224: ERROR_USER_MAPPED_FILE occurs?
我想真正了解 ERROR_USER_MAPPED_FILE
何时发生。所以我写了一些片段。重现错误。但它没有用。请帮我修复我的代码
进程 1:
HANDLE hFile = CreateFile("C:\test\full.exe", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return GetLastError();
HANDLE hMapFile = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
if (hMapFile == INVALID_HANDLE_VALUE)
return GetLastError();
mapHandles.push_back(hMapFile);
viewHandles.push_back(MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0));
我正在暂停该进程,并且在此进程中我还没有关闭地图和文件句柄的任何视图,以便其他进程尝试打开该文件时。我以为会抛出错误1224。
进程 2:
HANDLE hFile = CreateFile("C:\test\full.exe", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
cout << "Error Code : " << GetLastError() << endl;
char buffer[1025];
DWORD bytesRead;
if (!ReadFile(hFile, buffer, 1024, &bytesRead, 0))
cout << "Error Code : " << GetLastError() << endl;
CreateFile
和ReadFile
在过程2中成功。
其实我正在尝试单独处理这个错误1224。这意味着当文件因错误 32 而失败时,我想做点什么。如果文件因错误 1224 而失败,我想做点什么。
现在我必须测试那些案例。为了测试这些场景,我应该重现错误 1224。
ERROR_USER_MAPPED_FILE
或当您尝试删除或覆盖已被其他进程映射的文件时出现错误 1224。
进程#1
HANDLE hFile = CreateFile("C:\test\full.exe", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return GetLastError();
HANDLE hMapFile = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
if (hMapFile == INVALID_HANDLE_VALUE)
return GetLastError();
mapHandles.push_back(hMapFile);
viewHandles.push_back(MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0));
进程#2
HANDLE hFile = CreateFile("C:\test\full.exe", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
if(GetLastError() == 1224)
// File has been mapped by other process
else
// some other issue
}
在进程 #2 中,CREATE_ALWAYS
尝试覆盖已映射的文件。所以它最终抛出错误 1224.
I want to really understand when the ERROR_USER_MAPPED_FILE
occurs
如果真的理解让一些额外的信息。
起初这个错误是从内核返回的。所以它最初是 NTSTATUS
错误代码,然后由 RtlNtStatusToDosError
转换为 win32 错误。 api 反向翻译不存在 - 因为它不是唯一的,但可能您自己编写代码,创建反向翻译图。两个 NTSTATUS
代码被翻译成 ERROR_USER_MAPPED_FILE
:STATUS_USER_MAPPED_FILE
和 STATUS_PURGE_FAILED
:
if (
RtlNtStatusToDosError(STATUS_USER_MAPPED_FILE) != ERROR_USER_MAPPED_FILE
||
RtlNtStatusToDosError(STATUS_PURGE_FAILED) != ERROR_USER_MAPPED_FILE
)
{
__debugbreak();
}
要完全理解何时返回此代码需要查看文件系统源代码。我们有 fastfat
个例子。如果搜索 STATUS_USER_MAPPED_FILE
- 我们可以发现此代码从 4 处返回:
FatSupersedeOrOverwriteFile
- 当我们尝试调用
ZwCreateFile
与 FILE_OVERWRITE_IF
或 FILE_SUPERSEDE
CreateOption
或当我们用 CREATE_ALWAYS
调用 CreateFile
时
FatSetEndOfFileInfo
- when we call ZwSetInformationFile
具有 FileEndOfFileInformation
or SetEndOfFile
功能
FatSetValidDataLengthInfo
- 当我们调用
ZwSetInformationFile
与
FileValidDataLengthInformation
or SetFileValidData
功能(为此我们需要SE_MANAGE_VOLUME_PRIVILEGE
)
FatSetAllocationInfo
- 当我们使用 ZwSetInformationFile
使用 FileAllocationInformation
(无 win32 api shell)
您可以在此处记下常见模式:
if (!MmCanFileBeTruncated()) return STATUS_USER_MAPPED_FILE;
关于重现此错误的演示代码 - 您需要 两个 进程?!?单个进程中的单个例程 - 绰绰有余。
void test()
{
// for simplicity, i have access to this location as admin
STATIC_OBJECT_ATTRIBUTES(oa, "\systemroot\temp\.tmp");
HANDLE hFile, hSection, hFile2;
IO_STATUS_BLOCK iosb;
LARGE_INTEGER AllocationSize = { PAGE_SIZE };
NTSTATUS status;
if (0 <= NtCreateFile(&hFile, FILE_GENERIC_WRITE|FILE_GENERIC_READ, &oa, &iosb, &AllocationSize, 0,
FILE_SHARE_VALID_FLAGS, FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, 0, 0))
{
status = NtCreateSection(&hSection, SECTION_MAP_READ|SECTION_MAP_WRITE, 0, &AllocationSize, PAGE_READWRITE, SEC_COMMIT, hFile);
if (0 <= status)
{
PVOID BaseAddress = 0;
SIZE_T ViewSize = 0;
status = ZwMapViewOfSection(hSection, NtCurrentProcess(), &BaseAddress, 0, 0, 0, &ViewSize, ViewUnmap, 0, PAGE_READONLY);
NtClose(hSection);
if (0 <= status)
{
LARGE_INTEGER Eof = {};
// SetEndOfFile win32 api
status = ZwSetInformationFile(hFile, &iosb, &Eof, sizeof(Eof), FileEndOfFileInformation);
if (status != STATUS_USER_MAPPED_FILE) __debugbreak();
// no win32 api
status = ZwSetInformationFile(hFile, &iosb, &Eof, sizeof(Eof), FileAllocationInformation);
if (status != STATUS_USER_MAPPED_FILE) __debugbreak();
// SetFileValidData win32 api
// we need have SE_MANAGE_VOLUME_NAME privilege, otherwise STATUS_PRIVILEGE_NOT_HELD
status = ZwSetInformationFile(hFile, &iosb, &Eof, sizeof(Eof), FileValidDataLengthInformation);
switch (status)
{
case STATUS_USER_MAPPED_FILE:
case STATUS_PRIVILEGE_NOT_HELD:
break;
default: __debugbreak();
}
//CreateFileW(L"\\?\c:\windows\temp\.tmp", FILE_GENERIC_READ|FILE_GENERIC_WRITE, FILE_SHARE_VALID_FLAGS, 0, CREATE_ALWAYS, 0, 0);
status = NtCreateFile(&hFile2, FILE_GENERIC_WRITE|FILE_GENERIC_READ, &oa, &iosb, 0, 0,
FILE_SHARE_VALID_FLAGS, FILE_OVERWRITE_IF, FILE_SYNCHRONOUS_IO_NONALERT, 0, 0);
if (status != STATUS_USER_MAPPED_FILE) __debugbreak();
status = NtCreateFile(&hFile2, FILE_GENERIC_WRITE|FILE_GENERIC_READ, &oa, &iosb, 0, 0,
FILE_SHARE_VALID_FLAGS, FILE_SUPERSEDE, FILE_SYNCHRONOUS_IO_NONALERT, 0, 0);
if (status != STATUS_USER_MAPPED_FILE) __debugbreak();
ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
}
}
NtClose(hFile);
}
}
about STATUS_PURGE_FAILED
- look like in 调用时可以返回 WriteFile
- look here
- but i can not reproduce it in test. however very rarely this error can occur - "STATUS_PURGE_FAILED" error when you perform VM replications by using SCVMM in Windows Server 2012 R2
我想真正了解 ERROR_USER_MAPPED_FILE
何时发生。所以我写了一些片段。重现错误。但它没有用。请帮我修复我的代码
进程 1:
HANDLE hFile = CreateFile("C:\test\full.exe", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return GetLastError();
HANDLE hMapFile = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
if (hMapFile == INVALID_HANDLE_VALUE)
return GetLastError();
mapHandles.push_back(hMapFile);
viewHandles.push_back(MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0));
我正在暂停该进程,并且在此进程中我还没有关闭地图和文件句柄的任何视图,以便其他进程尝试打开该文件时。我以为会抛出错误1224。
进程 2:
HANDLE hFile = CreateFile("C:\test\full.exe", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
cout << "Error Code : " << GetLastError() << endl;
char buffer[1025];
DWORD bytesRead;
if (!ReadFile(hFile, buffer, 1024, &bytesRead, 0))
cout << "Error Code : " << GetLastError() << endl;
CreateFile
和ReadFile
在过程2中成功。
其实我正在尝试单独处理这个错误1224。这意味着当文件因错误 32 而失败时,我想做点什么。如果文件因错误 1224 而失败,我想做点什么。
现在我必须测试那些案例。为了测试这些场景,我应该重现错误 1224。
ERROR_USER_MAPPED_FILE
或当您尝试删除或覆盖已被其他进程映射的文件时出现错误 1224。
进程#1
HANDLE hFile = CreateFile("C:\test\full.exe", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return GetLastError();
HANDLE hMapFile = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
if (hMapFile == INVALID_HANDLE_VALUE)
return GetLastError();
mapHandles.push_back(hMapFile);
viewHandles.push_back(MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0));
进程#2
HANDLE hFile = CreateFile("C:\test\full.exe", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
if(GetLastError() == 1224)
// File has been mapped by other process
else
// some other issue
}
在进程 #2 中,CREATE_ALWAYS
尝试覆盖已映射的文件。所以它最终抛出错误 1224.
I want to really understand when the
ERROR_USER_MAPPED_FILE
occurs
如果真的理解让一些额外的信息。
起初这个错误是从内核返回的。所以它最初是 NTSTATUS
错误代码,然后由 RtlNtStatusToDosError
转换为 win32 错误。 api 反向翻译不存在 - 因为它不是唯一的,但可能您自己编写代码,创建反向翻译图。两个 NTSTATUS
代码被翻译成 ERROR_USER_MAPPED_FILE
:STATUS_USER_MAPPED_FILE
和 STATUS_PURGE_FAILED
:
if (
RtlNtStatusToDosError(STATUS_USER_MAPPED_FILE) != ERROR_USER_MAPPED_FILE
||
RtlNtStatusToDosError(STATUS_PURGE_FAILED) != ERROR_USER_MAPPED_FILE
)
{
__debugbreak();
}
要完全理解何时返回此代码需要查看文件系统源代码。我们有 fastfat
个例子。如果搜索 STATUS_USER_MAPPED_FILE
- 我们可以发现此代码从 4 处返回:
FatSupersedeOrOverwriteFile
- 当我们尝试调用ZwCreateFile
与FILE_OVERWRITE_IF
或FILE_SUPERSEDE
CreateOption
或当我们用CREATE_ALWAYS
调用 FatSetEndOfFileInfo
- when we callZwSetInformationFile
具有FileEndOfFileInformation
orSetEndOfFile
功能FatSetValidDataLengthInfo
- 当我们调用ZwSetInformationFile
与FileValidDataLengthInformation
orSetFileValidData
功能(为此我们需要SE_MANAGE_VOLUME_PRIVILEGE
)FatSetAllocationInfo
- 当我们使用ZwSetInformationFile
使用FileAllocationInformation
(无 win32 api shell)
CreateFile
时
您可以在此处记下常见模式:
if (!MmCanFileBeTruncated()) return STATUS_USER_MAPPED_FILE;
关于重现此错误的演示代码 - 您需要 两个 进程?!?单个进程中的单个例程 - 绰绰有余。
void test()
{
// for simplicity, i have access to this location as admin
STATIC_OBJECT_ATTRIBUTES(oa, "\systemroot\temp\.tmp");
HANDLE hFile, hSection, hFile2;
IO_STATUS_BLOCK iosb;
LARGE_INTEGER AllocationSize = { PAGE_SIZE };
NTSTATUS status;
if (0 <= NtCreateFile(&hFile, FILE_GENERIC_WRITE|FILE_GENERIC_READ, &oa, &iosb, &AllocationSize, 0,
FILE_SHARE_VALID_FLAGS, FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, 0, 0))
{
status = NtCreateSection(&hSection, SECTION_MAP_READ|SECTION_MAP_WRITE, 0, &AllocationSize, PAGE_READWRITE, SEC_COMMIT, hFile);
if (0 <= status)
{
PVOID BaseAddress = 0;
SIZE_T ViewSize = 0;
status = ZwMapViewOfSection(hSection, NtCurrentProcess(), &BaseAddress, 0, 0, 0, &ViewSize, ViewUnmap, 0, PAGE_READONLY);
NtClose(hSection);
if (0 <= status)
{
LARGE_INTEGER Eof = {};
// SetEndOfFile win32 api
status = ZwSetInformationFile(hFile, &iosb, &Eof, sizeof(Eof), FileEndOfFileInformation);
if (status != STATUS_USER_MAPPED_FILE) __debugbreak();
// no win32 api
status = ZwSetInformationFile(hFile, &iosb, &Eof, sizeof(Eof), FileAllocationInformation);
if (status != STATUS_USER_MAPPED_FILE) __debugbreak();
// SetFileValidData win32 api
// we need have SE_MANAGE_VOLUME_NAME privilege, otherwise STATUS_PRIVILEGE_NOT_HELD
status = ZwSetInformationFile(hFile, &iosb, &Eof, sizeof(Eof), FileValidDataLengthInformation);
switch (status)
{
case STATUS_USER_MAPPED_FILE:
case STATUS_PRIVILEGE_NOT_HELD:
break;
default: __debugbreak();
}
//CreateFileW(L"\\?\c:\windows\temp\.tmp", FILE_GENERIC_READ|FILE_GENERIC_WRITE, FILE_SHARE_VALID_FLAGS, 0, CREATE_ALWAYS, 0, 0);
status = NtCreateFile(&hFile2, FILE_GENERIC_WRITE|FILE_GENERIC_READ, &oa, &iosb, 0, 0,
FILE_SHARE_VALID_FLAGS, FILE_OVERWRITE_IF, FILE_SYNCHRONOUS_IO_NONALERT, 0, 0);
if (status != STATUS_USER_MAPPED_FILE) __debugbreak();
status = NtCreateFile(&hFile2, FILE_GENERIC_WRITE|FILE_GENERIC_READ, &oa, &iosb, 0, 0,
FILE_SHARE_VALID_FLAGS, FILE_SUPERSEDE, FILE_SYNCHRONOUS_IO_NONALERT, 0, 0);
if (status != STATUS_USER_MAPPED_FILE) __debugbreak();
ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
}
}
NtClose(hFile);
}
}
about STATUS_PURGE_FAILED
- look like in 调用时可以返回 WriteFile
- look here
- but i can not reproduce it in test. however very rarely this error can occur - "STATUS_PURGE_FAILED" error when you perform VM replications by using SCVMM in Windows Server 2012 R2