0

请看下面的更新

我一直在尝试修复 Ruby 库跨 UAC 上下文与另一个程序通信的能力,并且需要创建一个与当前用户具有相同安全属性的共享文件映射。我正在使用 Ruby/dl 并试图让它在 Ruby 1.9.3 上工作是导致我的问题的原因。

在 advapi31 中调用OpenProcessToken函数会导致分段错误。您将在下面找到一个最小示例,它导致我的机器出现分段错误。我收到的错误文本在这里,这里也是错误文本打印到命令行后出现的错误框的屏幕截图:

Ruby 问题对话框

require 'dl'
require 'dl/import'
require 'dl/types'

module Win
  extend DL::Importer

  dlload 'kernel32', 'advapi32'

  include DL::Win32Types

  # args: none
  # http://msdn.microsoft.com/en-us/library/windows/desktop/ms683179(v=vs.85).aspx
  extern 'HANDLE GetCurrentProcess()'

  # args: hProcessHandle, dwDesiredAccess, (out) phNewTokenHandle
  # http://msdn.microsoft.com/en-us/library/windows/desktop/aa379295(v=vs.85).aspx
  extern 'BOOL OpenProcessToken(HANDLE, DWORD, PHANDLE)'

  # args: hObject
  # http://msdn.microsoft.com/en-us/library/windows/desktop/ms724211(v=vs.85).aspx
  extern 'BOOL CloseHandle(HANDLE)'

  # args: none
  # http://msdn.microsoft.com/en-us/library/windows/desktop/ms679360(v=vs.85).aspx
  extern 'DWORD GetLastError()'

  def self.open_process_token
    token_handle = DL::CPtr.malloc(DL::SIZEOF_VOIDP, DL::RUBY_FREE)
    raise_error_if_zero(OpenProcessToken(Win.GetCurrentProcess, 0x8, token_handle.ref))
    raise_error_if_zero(CloseHandle(token_handle))
  end

  def self.raise_error_if_zero(result)
    if result == 0
      raise "Windows error: #{Win.GetLastError}"
    end
  end
end

Win.open_process_token

更新

将 Ruby 更新到 1.9.3p545(使用 RubyInstaller)允许我运行上面提供的示例,但我仍然遇到问题。我在这里创建了一个包含文件的要点,这些文件在使用 1.9.3p545 运行时会产生分段错误(尽管这次没有解释器变得无响应并产生上述对话框。)我已经在我的机器以及另一台安装相同版本 Ruby 的机器,结果相同。由于我之前没有提到它,我正在运行 Windows 7 Pro 64 位,我测试它的另一台计算机也是如此。

我注意到一些可能暗示更深层次的问题的事情,不一定与 OpenProcessToken 相关。以下任何一项都可以单独防止段错误:

  • 将 runner.rb 中的第 3 行复制到 mwe.rb 的底部并直接运行 mwe.rb。
  • 注释掉 mwe.rb 的第 5 行或注释掉一些较大的 errors.rb 子集(例如注释掉第 37 到 99 行不会导致段错误)。
  • 注释掉 runner.rb 的第 3 行,实际上只需要其他文件并退出。
  • 从 Pageant::Win 中注释掉以下组合不会导致段错误:
    • 来电extern
    • 来电struct
    • 常数
    • 类方法

在最后一种情况下,不需要注释掉特定类别的所有项目。例如,如果我注释掉TOKEN_USERSECURITY_ATTRIBUTES. 我还可以通过注释掉TOKEN_USERextern关联的语句来防止段错误IsValidSecurityDescriptor。我尝试了其他几种导致相同行为的组合。

任何帮助,将不胜感激。

4

1 回答 1

0

此错误不是由于 ruby​​,而是由于您的代码。

您在 open_process_token 方法中对 DL::CPtr 类型的变量使用了不适当的方法 ref。

方法 open_process_token

def self.open_process_token
  token_handle = DL::CPtr.malloc(DL::SIZEOF_VOIDP, DL::RUBY_FREE)
  OpenProcessToken(Win.GetCurrentProcess, 0x8, token_handle.ref)
end

应该

def self.open_process_token
  ptoken_handle = DL::CPtr.malloc(DL::SIZEOF_VOIDP, DL::RUBY_FREE)
  OpenProcessToken(Win.GetCurrentProcess, 0x8, ptoken_handle)
  token_handle = ptoken_handle.ptr.to_i
end

(感谢Heesob Park这个非问题上。)

于 2014-05-10T21:52:06.873 回答