【问题标题】:MapFileMemory(dwAllocSize: DWord); 'Hook DLL', 'Could not map file'MapFileMemory(dwAllocSize: DWord); '挂钩 DLL'、'无法映射文件'
【发布时间】:2016-07-10 00:16:07
【问题描述】:

在将旧的 32 位代码移植到 64 位时,我得到了

'Hook DLL', '无法映射文件'

我做错了什么?

var
  hObjHandle: THandle; //Variable for the file mapping object
  lpHookRec: PHookRec; //Pointer to our hook record

procedure MapFileMemory(dwAllocSize: DWord);
begin //MapFileMemory
  //Create a process wide memory mapped variable
  hObjHandle := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, dwAllocSize, 'HookRecMemBlock');
  if (hObjHandle = 0) then
    begin
      MessageBox(0, 'Hook DLL', 'Could not create file map object', mb_Ok);
      exit
    end;// (hObjHandle = 0)

  //Get a pointer to our process wide memory mapped variable
  lpHookRec := MapViewOfFile(hObjHandle, FILE_MAP_WRITE, 0, 0, dwAllocSize);
  if (lpHookRec = nil) then
    begin
      CloseHandle(hObjHandle);
      MessageBox(0, 'Hook DLL', 'Could not map file', mb_Ok);
      exit
    end //lpHookRec = Nil)
end; //MapFileMemory

procedure UnMapFileMemory;
begin //UnMapFileMemory
  //Delete our process wide memory mapped variable
  if (lpHookRec <> nil) then
    begin
      UnMapViewOfFile(lpHookRec);
      lpHookRec := nil
    end; // (lpHookRec <> Nil)
  if (hObjHandle > 0) then
    begin
      CloseHandle(hObjHandle);
      hObjHandle := 0
    end //(hObjHandle > 0)
end; // UnMapFileMemory


procedure DllEntryPoint(dwReason: DWord);
begin { DllEntryPoint }
  case dwReason of
    Dll_Process_Attach:
      begin
        {if we are getting mapped into a process, then get}
        {a pointer to our process wide memory mapped variable}
        hObjHandle := 0;
        lpHookRec := nil;
        MapFileMemory(sizeof(lpHookRec^))
      end;
    Dll_Process_Detach:
      begin
        {if we are getting unmapped from a process then, remove}
        {the pointer to our process wide memory mapped variable}
        UnMapFileMemory
      end;
  end { case dwReason }
end; { DllEntryPoint }

【问题讨论】:

  • 这是来自互联网的代码。
  • 阅读文档。我敢打赌,在 64 位上 CreateFileMapping 的第一个参数不是 $ffffffff。通过 INVALID_HANDLE_VALUE。试着理解你的代码,而不是盲目地复制它
  • 为什么要将项目更改为 64 位? x64 处理器也支持 32 位程序。 :-)
  • @Franciscocamilo,因为他想映射文件> 2GB。
  • @Franciscocamilo 实际上并非所有 64 位系统都可以运行 32 位程序。 Wow64 模拟器是运行 32 位应用程序所必需的,在某些 64 位版本的 Windows 上,该组件是可选并且可能未安装。

标签: delphi winapi 64-bit


【解决方案1】:

您需要进行相关更改以允许您在 64 位上运行这一事实。

哦,阅读 Raymond Chen 的 essential writings on DllMainthe followup
您真的不应该在DllMain 中进行内存映射文件的映射。
相反,您应该等到您的 dll 客户端开始调用您的 dll 中的任何工作例程,然后才进行映射。

最重要的是,如果您正在调试,include the actual error 总是一个好主意。

var
  hObjHandle: THandle; //Variable for the file mapping object
  lpHookRec: PHookRec; //Pointer to our hook record

procedure MapFileMemory(dwAllocSize: NativeUInt);
begin
  if Assigned(lpHookRec) then exit;
  hObjHandle := CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, dwAllocSize, 'HookRecMemBlock');
  if (hObjHandle = 0) then begin
    MessageBox(0, 'Hook DLL', 'Could not create file map object '#10#13+
               SysErrorMessage(GetLastError), mb_Ok);
    exit;
  end;

  //Get a pointer to our process wide memory mapped variable
  lpHookRec := MapViewOfFile(hObjHandle, FILE_MAP_WRITE, 0, 0, dwAllocSize);
  if (lpHookRec = nil) then begin
    CloseHandle(hObjHandle);
    MessageBox(0, 'Hook DLL', 'Could not map file '#10#13+
               SysErrorMessage(GetLastError), mb_Ok);
    exit;
  end; 
end;

procedure UnMapFileMemory;
begin 
  //Delete our process wide memory mapped variable
  if Assigned(lpHookRec) then begin
    UnMapViewOfFile(lpHookRec);
    lpHookRec := nil;
  end; 
  if (hObjHandle <> 0) then begin
    CloseHandle(hObjHandle);
    hObjHandle := 0;
  end; 
end;

var
  CS: TRTLCriticalSection;    

procedure DllEntryPoint(dwReason: DWord);
begin { DllEntryPoint }
  case dwReason of
    Dll_Process_Attach: begin
      {if we are getting mapped into a process, then get}
      {a pointer to our process wide memory mapped variable}
      hObjHandle := 0;
      lpHookRec := nil;
      //do not call MapMemFile here, do it when your work-routine is called for the first time.
    end;
    Dll_Process_Detach: begin
      {if we are getting unmapped from a process then, remove}
      {the pointer to our process wide memory mapped variable}
      EnterCriticalSection(CS);
        if Assigned(lpHookRec) then UnMapFileMemory;
      LeaveCriticalSection(CS);
    end;
  end; { case dwReason }
end; { DllEntryPoint }

【讨论】:

  • 除了对MessageBox 的调用之外,从DllMain 可以安全地执行其他所有操作。这在Dynamic-Link Library Best Practices 中有明确解释。
  • 哇,这有效但是,1)我无法添加 SysErrorMessage(GetLastError) 函数来了解实际错误(可能是,我需要包含一些单元,请告知)2)如果我不这样做t 在 DllMain 中包含 MapFileMemory(sizeof(lpHookRec^)),如何确定“首次使用”并运行该函数?
猜你喜欢
  • 1970-01-01
  • 2021-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
  • 2021-01-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多