何时出现错误1224:ERROR_USER_MAPPED_FILE?

时间:2017-01-25 06:26:53

标签: c++ winapi createfile

我想真正了解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;

CreateFileReadFile在流程2中成功。

实际上我正在尝试单独处理此错误1224。这意味着当文件因错误32而失败时我想做点什么。如果文件因错误1224而失败,我想做点什么。

现在我必须测试那些案例。为了测试这些场景,我应该重现错误1224。

2 个答案:

答案 0 :(得分:4)

  

我想真正了解ERROR_USER_MAPPED_FILE何时发生

如果真的理解,请提供一些额外信息。

首先从内核返回此错误。所以它最初是NTSTATUS错误代码,而不是由RtlNtStatusToDosError转换为win32错误。用于反向翻译的api不存在 - 因为它不是唯一的,但可能自己编写代码,从而创建反向翻译映射。两个NTSTATUS代码已转换为ERROR_USER_MAPPED_FILESTATUS_USER_MAPPED_FILESTATUS_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位返回:

你可以在这里注意到常见的模式:

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);
    }
}

关于重现此错误的演示代码 - 您需要两个进程?!?单一过程中的单一例程 - 绰绰有余。

STATUS_PURGE_FAILED

关于WriteFile - 当我们调用let parent = document.querySelector('.ms-list-addnew'); // get all child nodes -- including text nodes let childNodes = parent.childNodes; // reduce array to contain only text nodes let textNodes = Array.from(childNodes).filter(node => node.nodeType === Node.TEXT_NODE); for (let node of textNodes) { node.nodeValue = node.nodeValue.replace('või selle loendi', ''); } 时,可以返回看起来像here - 但我无法在测试中重现它。但是很少发生这种错误 - "STATUS_PURGE_FAILED" error when you perform VM replications by using SCVMM in Windows Server 2012 R2

答案 1 :(得分:1)

当您尝试删除或覆盖已由其他进程映射的文件时,会出现

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.