请参阅下面的更新
我一直在尝试修复Ruby库在UAC上下文中与另一个程序通信的能力,并且需要创建一个与当前用户具有相同安全属性的共享文件映射。我正在使用Ruby / dl并尝试将其用于Ruby 1.9.3是导致我的问题的原因。
在advapi31中调用OpenProcessToken函数会导致分段错误。您将在下面找到一个最小的示例,这会导致我的计算机出现分段错误。我收到的错误文本是here,这里也是错误文本打印到命令行后出现的错误框的屏幕截图:
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)允许我运行上面提供的示例,但我仍然遇到问题。我创建了一个包含文件的Gist here,当使用1.9.3p545运行时会产生分段错误(虽然这次没有解释器没有响应并生成如上所示的对话框。)我试过这个(和在我的机器上以及另一个安装了相同版本的Ruby的相同结果。由于我之前没有提到它,我正在运行Windows 7 Pro 64位,对于我测试的其他计算机也是如此。
我注意到一些可能意味着更深层次问题的事情,不一定与OpenProcessToken有关。以下任何一项都可以单独阻止段错误:
extern
struct
在最后一种情况下,没有必要注释掉特定类别的所有项目。例如,如果我注释掉TOKEN_USER
和SECURITY_ATTRIBUTES
,则会避免出现段错误。我还可以通过评论TOKEN_USER
和与extern
相关联的IsValidSecurityDescriptor
语句来阻止段错误。我尝试了其他几种导致相同行为的组合。
任何帮助都将不胜感激。
答案 0 :(得分: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 this上的{{3}}非问题。)