Please see the update below
I have been attempting to fix a Ruby library's ability to communicate with another program across UAC contexts and need to create a shared file map with the same security attributes as the current user. I'm using Ruby/dl and trying to get this to work on Ruby 1.9.3 is what led to my issue.
Calling the OpenProcessToken function in advapi31 results in a segmentation fault. You will find a minimal example below, which resulted in a segmentation fault on my machine. The text of the error I received is here, and here is also a screenshot of the error box that comes up after the error text prints to the command line:
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
Update
Updating Ruby to 1.9.3p545 (using RubyInstaller) allowed me to run the example provided above, but I continue to have issues. I have created a Gist here containing the files which, when run with 1.9.3p545, produce a segmentation fault (though this time without interpreter becoming unresponsive and producing the dialog box as above.) I have tried this (and the below) on my machine as well as another with the same version of Ruby installed with the same result. Since I didn't mention it previously, I'm running Windows 7 Pro 64-bit, the same is true for the other computer I tested it on.
I have noticed a few things that may imply a deeper issue, not necessarily associated with OpenProcessToken. Any one of the following may, individually, prevent a segfault:
- Copying line 3 from runner.rb to the bottom of mwe.rb and running mwe.rb directly.
- Commenting out line 5 of mwe.rb or commenting out some large subset of errors.rb (e.g. commenting out lines 37 through 99 result in no segfault).
- Commenting out line 3 of runner.rb, in effect only requiring the other files and exiting.
- Commenting out a combination of the following from within Pageant::Win results in no segfault:
- Calls to
extern
- Calls to
struct
- Constants
- Class methods
- Calls to
In the last case it is not necessary to comment out all of the items of a particular category. For instance, a segfault is avoided if I comment out TOKEN_USER
and SECURITY_ATTRIBUTES
. I may also prevent a segfault by commenting out TOKEN_USER
and the extern
statement associated with IsValidSecurityDescriptor
. I have tried several other combinations that result in the same behavior.
Any help would be appreciated.