以下のアップデートをご覧ください
UAC コンテキストを介して別のプログラムと通信する Ruby ライブラリの機能を修正しようとしており、現在のユーザーと同じセキュリティ属性を持つ共有ファイル マップを作成する必要があります。私は Ruby/dl を使用していますが、これを Ruby 1.9.3 で動作させようとしていることが問題の原因です。
advapi31 でOpenProcessToken関数を呼び出すと、セグメンテーション違反が発生します。以下に最小限の例を示します。これにより、私のマシンでセグメンテーション エラーが発生しました。受け取ったエラーのテキストはこちらです。エラー テキストがコマンド ラインに出力された後に表示されるエラー ボックスのスクリーンショットもここにあります。
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
アップデート
(RubyInstaller を使用して) Ruby を 1.9.3p545 に更新すると、上記の例を実行できましたが、引き続き問題が発生します。ここで、1.9.3p545 で実行するとセグメンテーション エラーが発生するファイルを含むGist を作成しました(ただし、今回はインタプリタが応答しなくなり、上記のダイアログ ボックスが表示されることはありません)。同じバージョンの Ruby がインストールされた別のマシンと同様に、同じ結果が得られます。以前は言及しなかったので、私は Windows 7 Pro 64 ビットを実行しています。同じことが、テストした他のコンピューターにも当てはまります。
必ずしも OpenProcessToken に関連しているとは限らない、より深い問題を暗示している可能性があるいくつかのことに気付きました。次のいずれかによって、個別にセグメンテーション違反を防ぐことができます。
- 行 3 を runner.rb から mwe.rb の下部にコピーし、mwe.rb を直接実行します。
- mwe.rb の 5 行目をコメント アウトするか、errors.rb のいくつかの大きなサブセットをコメント アウトします (たとえば、37 行目から 99 行目をコメント アウトすると、segfault は発生しません)。
- runner.rb の 3 行目をコメントアウトして、実際には他のファイルのみを要求して終了します。
- Pageant::Win 内から次の組み合わせをコメントアウトすると、segfault は発生しません。
- への呼び出し
extern
- への呼び出し
struct
- 定数
- クラス メソッド
- への呼び出し
最後のケースでは、特定のカテゴリのすべての項目をコメント化する必要はありません。たとえば、 と をコメントアウトするTOKEN_USER
と、セグメンテーション違反が回避されSECURITY_ATTRIBUTES
ます。また、コメント アウトTOKEN_USER
と にextern
関連付けられたステートメントによってセグメンテーション違反を防ぐこともできIsValidSecurityDescriptor
ます。同じ動作になる他のいくつかの組み合わせを試しました。
どんな助けでも大歓迎です。