![](/img/trans.png)
[英]boost::interprocess shared memory between 32 and 64 bit processes
[英]Issue when trying to write to memory mapped file, shared between two processes (32 bit -> 64 bit)
作為臨時解決方案,我正在實施一種通過 32 位 DLL 將一些數據獲取到 64 位應用程序的方法。
我讓它盡可能簡單,它不需要高性能或最漂亮的解決方案。 這個想法是不要在花哨的握手等上浪費太多時間。
為此,我的 64 位應用程序加載了我自己制作的 64 位 DLL(它具有與 32 位 DLL 相同的導出函數)。 因此,在主應用程序中,沒有任何變化。
64 位 DLL 通過在命令行上傳遞內存映射文件的名稱和一些其他輸入數據來創建內存映射文件並啟動 32 位幫助程序。
輔助可執行文件加載 32 位 DLL,調用 DLL function,將數據復制到共享內存映射文件中,退出,然后...... Bob 是你的叔叔。 也就是說.. 鮑勃今天過得很糟糕,它不起作用。 寫入內存映射文件的WriteFile()
失敗,出現 Windows API 錯誤 6 ( ERROR_INVALID_HANDLE
),如GetLastError()
所報告。
除了寫入內存映射文件外,一切正常(讀取也可能失敗,但還沒有做到)。
我確信問題在於我如何創建內存映射文件,我在這里完全無法理解,所以我很感激一雙新的眼睛。
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) ;
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) ;
}
}
}
}
程序退出並顯示此退出代碼:
return ((Status << 24) | BytesCopied) ;
根據我意識到的評論,我誤解了 FileMapping HANDLE
的使用和MapViewOfFile()
的目的。
我可以簡單地在MapViewOfFile()
返回的指針上使用memcpy()
,而不是在內存映射文件上使用ReadFile()
和WriteFile()
)
這是固定代碼:
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) ;
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) ;
}
}
}
}
程序退出並顯示此退出代碼:
return ((Status << 24) | BytesCopied) ;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.