Ven*_*esh 2 c++ winapi createfile
我想真正了解何时ERROR_USER_MAPPED_FILE发生。所以我写了一些片段。重现错误。但它没有用。请帮我修复我的代码
流程一:
    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发生
如果真的理解让一些额外的信息。
起初这个错误从内核返回。所以它最初是NTSTATUS错误代码,然后被转换为 win32 错误RtlNtStatusToDosError。用于反向翻译的 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或当我们CreateFile用CREATE_ALWAYSFatSetEndOfFileInfo- 当我们ZwSetInformationFile
用FileEndOfFileInformation或SetEndOfFile函数调用时FatSetValidDataLengthInfo- 当我们ZwSetInformationFile    用FileValidDataLengthInformation或SetFileValidData
函数调用
时
(我们需要有SE_MANAGE_VOLUME_PRIVILEGE这个)FatSetAllocationInfo- 当我们使用ZwSetInformationFile
with FileAllocationInformation(no 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- 但我无法在测试中重现它。但是很少会发生此错误 -"STATUS_PURGE_FAILED" error when you perform VM replications by using SCVMM in Windows Server 2012 R2
| 归档时间: | 
 | 
| 查看次数: | 1965 次 | 
| 最近记录: |