MapViewOfFile返回ERROR_INVALID_PARAMETER Windows-10(通用Windows平台)

问题描述 投票:0回答:1

我试图将我现有的Windows桌面应用程序(在Windows-7上运行正常)移植到Windows-10(通用Windows平台) 在Windows-10上,MapViewOfFile返回

ERROR_INVALID_PARAMETER

,当我设置访问类型为FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_EXECUTE。 我的代码如下:

   HANDLE mhandle = NULL;
   HANDLE g_hfile;
   LARGE_INTEGER ms_size;
   size_t file_size = 0;     
   void* map = NULL; 

   CREATEFILE2_EXTENDED_PARAMETERS ms_param;
   ms_param.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
   ms_param.dwFileAttributes = GENERIC_WRITE | GENERIC_EXECUTE;
   ms_param.dwFileFlags = FILE_FLAG_NO_BUFFERING;
   ms_param.dwSecurityQosFlags = SECURITY_DELEGATION;
   ms_param.lpSecurityAttributes = NULL;
   ms_param.hTemplateFile = NULL;
   g_hfile = CreateFile2(filename, GENERIC_WRITE | GENERIC_EXECUTE, FILE_SHARE_READ|FILE_SHARE_WRITE, OPEN_EXISTING, &ms_param);
   if (g_hfile == INVALID_HANDLE_VALUE)
   {
       return GetLastError();
   }

   if (GetFileSizeEx(g_hfile, &ms_size) == 0)
   {
       return GetLastError();
   }

   file_size = ms_size.u.LowPart | ((unsigned long long)ms_size.u.HighPart << 32 );
   mhandle = CreateFileMapping(g_hfile, NULL, PAGE_EXECUTE_READWRITE, (unsigned long long)ms_size.u.HighPart, ms_size.u.LowPart, NULL);
   if (mhandle == NULL)
   {
       return GetLastError();
   }

   map = MapViewOfFile(mhandle, FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_EXECUTE, 0, 0, file_size);
  if (map == NULL)
  {
     return GetLastError();
  }

被映射的文件大小约为1KB。如果我将访问类型设置为FILE_MAP_READ | FILE_MAP_WRITEFILE_MAP_READ | FILE_MAP_EXEC MapViewOfFile按预期工作。 但是,如果我使用FILE_MAP_READ | FILE_MAP_EXEC | FILE_MAP_EXECUTEFILE_MAP_EXEC | FILE_MAP_EXECUTE MapViewOfFile失败。 我没有找到任何关于此api的Windows-10特定文档。我在这里阅读了这个API的可用MSDN文档:https://msdn.microsoft.com/en-us/library/windows/desktop/aa366761(v=vs.85).aspx 此外,为UWP设置的API似乎不包含此api:https://msdn.microsoft.com/en-us/library/windows/desktop/mt186421(v=vs.85).aspx 任何建议将受到高度赞赏

windows file-io memory-mapped-files windows-10-universal
1个回答
1
投票

我认为你的问题不再适用,但希望我的回答对那些面临同样问题的人有所帮助。您正在使用正确的UWP API来创建文件,但用于文件映射的API是错误的。你需要使用CreateFileMappingFromApp而不是CreateFileMappingMapViewOfFileFromApp而不是MapViewOfFile。仔细看看,UWP CreateFileMappingFromApp的PageProtection类型根本不允许EXECUTE。

这里是代码示例,其中包含大量描述非明显片段的注释:

#include <windows.h>
#include <string>
#include <iostream>

// you may combine access in the same was as pageFileAccessMode allows
enum class AccessMode {
    READ,
    READ_WRITE
};

DWORD openFileForMapping(AccessMode accessMode, std::wstring const & filepath, HANDLE * fileHandler, std::size_t & fileSize, HANDLE * fileMappingHandler) {
    DWORD fileAccessRegularMode;
    DWORD fileAccessSharedMode;
    DWORD pageFileAccessMode;
    HANDLE localFileHandler;
    HANDLE localFileMappingHandler;

    switch (accessMode) {
    case AccessMode::READ:
        fileAccessRegularMode = GENERIC_READ;
        fileAccessSharedMode = FILE_SHARE_READ;
        pageFileAccessMode = PAGE_READONLY;
        break;
    case AccessMode::READ_WRITE:
        fileAccessRegularMode = GENERIC_READ | GENERIC_WRITE;
        fileAccessSharedMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
        pageFileAccessMode = PAGE_READWRITE;
        break;
    }

    // parameters MUST be initialized with zero and size
    CREATEFILE2_EXTENDED_PARAMETERS createFile2ParametersEx{ 0 };
    createFile2ParametersEx.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
    createFile2ParametersEx.dwFileAttributes = fileAccessRegularMode;
    // parameters options, depends on your requirements
    createFile2ParametersEx.dwFileFlags = FILE_FLAG_NO_BUFFERING;
    createFile2ParametersEx.lpSecurityAttributes = NULL;
    createFile2ParametersEx.hTemplateFile = NULL;

    localFileHandler = CreateFile2(filepath.c_str(), fileAccessRegularMode, fileAccessSharedMode, OPEN_EXISTING, &createFile2ParametersEx);
    if (localFileHandler == INVALID_HANDLE_VALUE) {
        return GetLastError();
    }

    LARGE_INTEGER msSize;
    if (GetFileSizeEx(localFileHandler, &msSize) == 0) {
        return GetLastError();
    }

    fileSize = msSize.QuadPart;
    localFileMappingHandler = CreateFileMappingFromApp(localFileHandler, NULL, pageFileAccessMode, fileSize, NULL);
    if (localFileMappingHandler == nullptr) {
        return GetLastError();
    }

    *fileHandler = localFileHandler;
    *fileMappingHandler = localFileMappingHandler;
    return S_OK;
}

DWORD getView(AccessMode accessMode, HANDLE fileMappingHandler, std::uint64_t beginIndex, std::uint64_t lengthOfView, void ** mapView) {
    DWORD mapViewAccessMode;

    switch (accessMode) {
    case AccessMode::READ:
        mapViewAccessMode = FILE_MAP_READ;
        break;
    case AccessMode::READ_WRITE:
        mapViewAccessMode = FILE_MAP_READ | FILE_MAP_WRITE;
        break;
    }

    *mapView = MapViewOfFileFromApp(fileMappingHandler, mapViewAccessMode, beginIndex, lengthOfView);
    if (*mapView == nullptr) {
        return GetLastError();
    }

    return S_OK;
}

DWORD getFileMapViewAndPrint() {
    DWORD errorCode;
    // don't forget, UWP app have write access only inside container local folder
    std::wstring filename = L"test.txt";

    // open file with desired acces and create file mapping 
    HANDLE fileHandle;
    HANDLE fileMappingHandle;
    std::size_t fileSize;
    errorCode = openFileForMapping(AccessMode::READ, filename.c_str(), &fileHandle, fileSize, &fileMappingHandle);
    if (errorCode != S_OK) {
        return errorCode;
    }

    // using created file mapping project map view to file
    void * mapView;
    errorCode = getView(AccessMode::READ, fileMappingHandle, 0, fileSize, &mapView);
    if (errorCode != S_OK) {
        return errorCode;
    }

    // mapView now contains row data from file, in my case it was txt
    // with UTF8 text so I just need to cast void to char
    OutputDebugStringA(static_cast<char*>(mapView));
    OutputDebugStringA("\n");

    // cleanup
    UnmapViewOfFile(mapView);
    mapView = nullptr;
    CloseHandle(fileMappingHandle);
    CloseHandle(fileHandle);

    return S_OK;
}
© www.soinside.com 2019 - 2024. All rights reserved.