[英]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.