简体   繁体   English

尝试写入 memory 映射文件时出现问题,在两个进程之间共享(32 位 -> 64 位)

[英]Issue when trying to write to memory mapped file, shared between two processes (32 bit -> 64 bit)

As a temp solution I'm implementing a way to get some data via a 32-bit DLL to a 64-bit application.作为临时解决方案,我正在实施一种通过 32 位 DLL 将一些数据获取到 64 位应用程序的方法。

I'm keeping it as simple as possible, it doesn't need to be high performance or the most beautiful solution.我让它尽可能简单,它不需要高性能或最漂亮的解决方案。 The idea is not to waste too much time on fancy handshaking, etc.这个想法是不要在花哨的握手等上浪费太多时间。

To that end, my 64-bit application loads a 64-bit DLL of my own making (which has the same exported functions as the 32-bit DLL).为此,我的 64 位应用程序加载了我自己制作的 64 位 DLL(它具有与 32 位 DLL 相同的导出函数)。 So, in the main app, nothing changes.因此,在主应用程序中,没有任何变化。

The 64-bit DLL creates a memory-mapped file and starts a 32-bit helper program, by passing the name of the memory-mapped file and some other input data on the command line. 64 位 DLL 通过在命令行上传递内存映射文件的名称和一些其他输入数据来创建内存映射文件并启动 32 位帮助程序。

The helper executable loads the 32-bit DLL, calls a DLL function, copies the data into the shared memory-mapped file, exits, and.. Bob's your uncle.辅助可执行文件加载 32 位 DLL,调用 DLL function,将数据复制到共享内存映射文件中,退出,然后...... Bob 是你的叔叔。 That is to say.. Bob is having a bad day, it doesn't work.也就是说.. 鲍勃今天过得很糟糕,它不起作用。 WriteFile() to the memory-mapped file fails with Windows API error 6 ( ERROR_INVALID_HANDLE ), as reported by GetLastError() .写入内存映射文件的WriteFile()失败,出现 Windows API 错误 6 ( ERROR_INVALID_HANDLE ),如GetLastError()所报告。

Everything works except for writing to the memory-mapped file (reading probably fails as well, but haven't been able to get to that yet).除了写入内存映射文件外,一切正常(读取也可能失败,但还没有做到)。

I'm sure the issue is with how I create the memory-mapped file, I'm thoroughly out of my depth here, so I appreciate a fresh pair of eyes.我确信问题在于我如何创建内存映射文件,我在这里完全无法理解,所以我很感激一双新的眼睛。

Relevant code in the 64-bit DLL: 64位DLL中的相关代码:

char MemoryFileName[] = "unique_name_with_extra_random_chars";

HANDLE MemoryFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, 
PAGE_EXECUTE_READWRITE, 0, (256 * 1024), MemoryFileName) ;

if (MemoryFile)
    {
    void *View = MapViewOfFile(MemoryFile, FILE_MAP_ALL_ACCESS, 0, 0, 0) ;

    char Exe[] = "Hlpr.exe" ;
    char Cmd[2048] = "Hlpr.exe " ;

    strcat(Cmd, "\"") ;
    strcat(Cmd, MemoryFileName) ;
    strcat(Cmd, "\" \"") ;
    strcat(Cmd, "262144") ; // (256 * 1024)
    strcat(Cmd, "\" \"") ;
    strcat(Cmd, file_name_path_of_data_the_dll_needs_to_parse) ;
    strcat(Cmd, "\"") ;

    STARTUPINFO StartupInfo = {sizeof StartupInfo} ; // Init
    PROCESS_INFORMATION ProcessInfo ;

    if (CreateProcess(Exe, Cmd, NULL, NULL, false, 0, NULL, NULL, 
        &StartupInfo, &ProcessInfo))
        {
        if (WaitForSingleObject(ProcessInfo.hProcess, INFINITE) == WAIT_OBJECT_0)
            {
            DWORD ExitCode ;
            if (GetExitCodeProcess(ProcessInfo.hProcess, &ExitCode))
                {
                Status = (ExitCode >> 24) ; // Feedback from the dll function

                if (Status == DLL_FUNCTION_OK)
                    {
                    DWORD Size = (ExitCode & 0x00FFFFFF) ;

                    if (Size)
                        {
                        BYTE *Buffer = new BYTE[Size] ;
                        Dll_function_return_Data = 
                            (Dll_function_return_Data_Type*)Buffer ;

                        SetFilePointer(MemoryFile, 0, 0, FILE_BEGIN) ;

                        DWORD BytesCopied ;
                        ReadFile(MemoryFile, Buffer, Size, &BytesCopied, NULL) ;

                        if (BytesCopied != Size)
                            Status = MY_ERROR ;
                        }
                    }
                }
            }

        CloseHandle(ProcessInfo.hProcess) ;
        CloseHandle(ProcessInfo.hThread) ;
        }
    UnmapViewOfFile(View) ;
    }

CloseHandle(MemoryFile) ;

Relevant code in the 32-bit Hlpr.exe : 32位的Hlpr.exe中的相关代码:

if (ParamCount() >= 3)
    {
    String DllPath = StringReplace(ParamStr(0), L"Hlpr.exe", 
    L"the_32bit_dll.dll", TReplaceFlags() << rfReplaceAll) ;

    DllHandle = LoadLibraryExW(DllPath.c_str(), NULL, 0) ;

    if (DllHandle)
        {
        // Here the dll exported function pointers are collected (GetProcAddress())

        if (dll_function_pointer)
            {
            MemoryFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, 
                         ParamStr(1).c_str()) ;

            if (MemoryFile)
                {
                void *View = MapViewOfFile(MemoryFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);

                DWORD SizeOfMappedFile = ParamStr(2).ToInt() ;

                if (SizeOfMappedFile)
                    {
                    AnsiString ImageFileNameA(ParamStr(3)) ;

                    DWORD Size ;
                    Dll_function_return_Data_Type *Dll_function_return_Data ;

                    Status = dll_function_pointer(ImageFileNameA.c_str(), 
                             Dll_function_return_Data, Size) ; 

                    if (Status == DLL_FUNCTION_OK)
                        {
                        if (SizeOfMappedFile >= Size)
                            {
                            SetFilePointer(MemoryFile, 0, 0, FILE_BEGIN) ;

                            if (WriteFile(MemoryFile, (BYTE*)Dll_function_return_Data,
                                Size, &BytesCopied, NULL)) // FAILS
                                {
                                if (Size != BytesCopied)
                                    Status = MY_ERROR ;
                                }
                            else
                                {
                                LOG("Error: %u", GetLastError()) ; // Returns error 6
                                Status = MY_ERROR ;
                                }
                            }
                        else
                            Status = MY_ERROR ;
                        }
                    }
                UnmapViewOfFile(View) ;
                }
            }
        }
    }

The program exits with this exit code:程序退出并显示此退出代码:

return ((Status << 24) | BytesCopied) ;

Based on the comments I realized I misunderstood the use of a FileMapping HANDLE and the purpose of MapViewOfFile() .根据我意识到的评论,我误解了 FileMapping HANDLE的使用和MapViewOfFile()的目的。

Instead of using ReadFile() and WriteFile() on the memory-mapped file I can simply use memcpy() on the pointer returned by MapViewOfFile()我可以简单地在MapViewOfFile()返回的指针上使用memcpy() ,而不是在内存映射文件上使用ReadFile()WriteFile() )

Here is the fixed code:这是固定代码:

Relevant code in the 64-bit DLL: 64位DLL中的相关代码:

char MemoryFileName[] = "unique_name_with_extra_random_chars";

HANDLE MemoryFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, 
PAGE_EXECUTE_READWRITE, 0, (256 * 1024), MemoryFileName) ;

if (MemoryFile)
    {
    void *Mem = MapViewOfFile(MemoryFile, FILE_MAP_ALL_ACCESS, 0, 0, 0) ;

    char Exe[] = "Hlpr.exe" ;
    char Cmd[2048] = "Hlpr.exe " ;

    strcat(Cmd, "\"") ;
    strcat(Cmd, MemoryFileName) ;
    strcat(Cmd, "\" \"") ;
    strcat(Cmd, "262144") ; // (256 * 1024)
    strcat(Cmd, "\" \"") ;
    strcat(Cmd, file_name_path_of_data_the_dll_needs_to_parse) ;
    strcat(Cmd, "\"") ;

    STARTUPINFO StartupInfo = {sizeof StartupInfo} ; // Init
    PROCESS_INFORMATION ProcessInfo ;

    if (Mem && CreateProcess(Exe, Cmd, NULL, NULL, false, 0, NULL, NULL, 
        &StartupInfo, &ProcessInfo))
        {
        if (WaitForSingleObject(ProcessInfo.hProcess, INFINITE) == WAIT_OBJECT_0)
            {
            DWORD ExitCode ;
            if (GetExitCodeProcess(ProcessInfo.hProcess, &ExitCode))
                {
                Status = (ExitCode >> 24) ; // Feedback from the dll function

                if (Status == DLL_FUNCTION_OK)
                    {
                    DWORD Size = (ExitCode & 0x00FFFFFF) ;

                    if (Size)
                        {
                        BYTE *Buffer = new BYTE[Size] ;
                        Dll_function_return_Data = 
                            (Dll_function_return_Data_Type*)Buffer ;

                        memcpy(Buffer, Mem, Size) ;
                        }
                    }
                }
            }

        CloseHandle(ProcessInfo.hProcess) ;
        CloseHandle(ProcessInfo.hThread) ;
        }
    UnmapViewOfFile(Mem) ;
    }

CloseHandle(MemoryFile) ;

Relevant code in the 32-bit Hlpr.exe : 32位的Hlpr.exe中的相关代码:

if (ParamCount() >= 3)
    {
    String DllPath = StringReplace(ParamStr(0), L"Hlpr.exe", 
    L"the_32bit_dll.dll", TReplaceFlags() << rfReplaceAll) ;

    DllHandle = LoadLibraryExW(DllPath.c_str(), NULL, 0) ;

    if (DllHandle)
        {
        // Here the dll exported function pointers are collected (GetProcAddress())

        if (dll_function_pointer)
            {
            MemoryFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, 
                         ParamStr(1).c_str()) ;

            if (MemoryFile)
                {
                void *Mem = MapViewOfFile(MemoryFile, FILE_MAP_ALL_ACCESS, 0, 0, 0) ;

                DWORD SizeOfMappedFile = ParamStr(2).ToInt() ;

                if (Mem && SizeOfMappedFile)
                    {
                    AnsiString ImageFileNameA(ParamStr(3)) ;

                    DWORD Size ;
                    Dll_function_return_Data_Type *Dll_function_return_Data ;

                    Status = dll_function_pointer(ImageFileNameA.c_str(), 
                             Dll_function_return_Data, Size) ; 

                    if (Status == DLL_FUNCTION_OK)
                        {
                        if (SizeOfMappedFile >= Size)
                            {
                            memcpy(Mem, (BYTE*)Dll_function_return_Data, Size) ; 
                            BytesCopied = Size ;
                            }
                        else
                            Status = MY_ERROR ;
                        }
                    }
                UnmapViewOfFile(Mem) ;
                }
            }
        }
    }

The program exits with this exit code:程序退出并显示此退出代码:

return ((Status << 24) | BytesCopied) ;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 boost::interprocess 32 和 64 位进程之间的共享内存 - boost::interprocess shared memory between 32 and 64 bit processes MapViewOfFile在32位和64位进程之间共享 - MapViewOfFile shared between 32bit and 64bit processes 32位和64位增强过程之间的IPC - IPC between 32 bit and 64 bit boost processes 使用从Solaris 64位或Linux 32位到Linux 64位的内存映射文件 - Use memory mapped files from Solaris 64 Bit or Linux 32 Bit to Linux 64 Bit 链接到32位环境中的32位共享对象文件会生成ELFCLASS64错误 - Linking to 32bit shared object file in 32 bit enviornment generates ELFCLASS64 error 从32位进程挂接64位进程时,SetWindowsHookEx()不会返回错误? - SetWindowsHookEx() doesn't return an error when hooking 64 bit processes from a 32 bit process? 如何测试共享的 object 是 32 位还是 64 位? - How to test if a shared object is 32-bit or 64-bit? 在 64 位系统上使用 32 位共享库 - Using 32-bit shared libraries on 64-bit system 内存映射在64位OS上运行的32位软件中的巨大文件 - Memory mapping a huge file in 32 bit software running on 64 bit OS 我该如何使用64位而不是32位解决按位seive? 两者有什么区别? - How can I solve bitwise seive using 64 bit instead of 32 bit? What is the difference between these two?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM