lib/win32/event.rb in win32-event-0.5.2 vs lib/win32/event.rb in win32-event-0.6.0

- old
+ new

@@ -3,35 +3,50 @@ # The Win32 module serves as a namespace only. module Win32 # The Event class encapsulates Windows event objects. class Event < Ipc - + ffi_lib :kernel32 + + class SecurityAttributes < FFI::Struct + layout( + :nLength, :ulong, + :lpSecurityDescriptor, :pointer, + :bInheritHandle, :bool + ) + end + + attach_function :CreateEvent, :CreateEventW, [:pointer, :bool, :bool, :buffer_in], :ulong + attach_function :OpenEvent, :OpenEventW, [:ulong, :bool, :buffer_in], :ulong + attach_function :SetEvent, [:ulong], :bool + attach_function :ResetEvent, [:ulong], :bool + + private_class_method :CreateEvent, :OpenEvent, :SetEvent, :ResetEvent + + INVALID_HANDLE_VALUE = 0xFFFFFFFF + EVENT_ALL_ACCESS = 0x1F0003 + # This is the error raised if any of the Event methods fail. class Error < StandardError; end - - extend Windows::Synchronize - extend Windows::Error - extend Windows::Handle - + # The version of the win32-event library - VERSION = '0.5.2' - - # The name of the Event object. + VERSION = '0.6.0' + + # The name of the Event object. The default is nil # attr_reader :name - + # Indicates whether or not the Event requires use of the ResetEvent() - # function set the state to nonsignaled. + # function set the state to nonsignaled. The default is false # attr_reader :manual_reset - + # The initial state of the Event object. If true, the initial state - # is signaled. Otherwise, it is non-signaled. + # is signaled. Otherwise, it is non-signaled. The default is false. # attr_reader :initial_state - + # Creates and returns new Event object. If +name+ is omitted, the # Event object is created without a name, i.e. it's anonymous. # # If +name+ is provided and it already exists, then it is opened # instead and the +manual_reset+ and +initial_state+ parameters are @@ -46,53 +61,46 @@ # If the +init_state+ parameter is +true+, the initial state of the # Event object is signaled; otherwise, it is nonsignaled (the default). # # If the +inherit+ parameter is true, then processes created by this # process will inherit the handle. Otherwise they will not. - # + # # In block form this will automatically close the Event object at the # end of the block. - # + # def initialize(name=nil, man_reset=false, init_state=false, inherit=true) @name = name @manual_reset = man_reset @initial_state = init_state @inherit = inherit - - manual_reset = man_reset ? 1 : 0 - initial_state = init_state ? 1 : 0 - - # Used to prevent potential segfaults. - if name && !name.is_a?(String) - raise TypeError, 'name must be a string' + + if name.is_a?(String) + if name.encoding.to_s != 'UTF-16LE' + name = name + 0.chr + name.encode!('UTF-16LE') + end + else + raise TypeError if name end if inherit - sec = 0.chr * 12 # sizeof(SECURITY_ATTRIBUTES) - sec[0,4] = [12].pack('L') - sec[8,4] = [1].pack('L') # 1 == TRUE + sec = SecurityAttributes.new + sec[:nLength] = SecurityAttributes.size + sec[:bInheritHandle] = inherit else - sec = 0 + sec = nil end - + handle = CreateEvent(sec, manual_reset, initial_state, name) - + if handle == 0 || handle == INVALID_HANDLE_VALUE - raise Error, get_last_error + raise SystemCallError.new("CreateEvent", FFI.errno) end - + super(handle) - - if block_given? - begin - yield self - ensure - close - end - end end - + # Open an existing Event by +name+. The +inherit+ argument sets whether # or not the object was opened such that a process created by the # CreateProcess() function (a Windows API function) can inherit the # handle. The default is true. # @@ -102,64 +110,67 @@ # event doesn't already exist. # # If you want "open or create" semantics, then use Event.new. # def self.open(name, inherit=true, &block) - if name && !name.is_a?(String) - raise TypeError, 'name must be a string' + raise TypeError unless name.is_a?(String) + + if name.encoding.to_s != 'UTF-16LE' + oname = name + 0.chr + oname.encode!('UTF-16LE') + else + oname = name.dup end - - bool = inherit ? 1 : 0 # This block of code is here strictly to force an error if the user # tries to open an event that doesn't already exist. begin - handle = OpenEvent(EVENT_ALL_ACCESS, bool, name) + h = OpenEvent(EVENT_ALL_ACCESS, inherit, oname) - if handle == 0 || handle == INVALID_HANDLE_VALUE - raise Error, get_last_error + if h == 0 || h == INVALID_HANDLE_VALUE + raise SystemCallError.new("OpenEvent", FFI.errno) end ensure - CloseHandle(handle) if handle > 0 + CloseHandle(h) if h end self.new(name, false, false, inherit, &block) end - + # Returns whether or not the object was opened such that a process # created by the CreateProcess() function (a Windows API function) can # inherit the handle. The default is true. # def inheritable? @inherit end - + # Sets the Event object to a non-signaled state. - # + # def reset unless ResetEvent(@handle) - raise Error, get_last_error + raise SystemCallError.new("ResetEvent", FFI.errno) end @signaled = false end - + # Sets the Event object to a signaled state. - # + # def set unless SetEvent(@handle) - raise Error, get_last_error + raise SystemCallError.new("SetEvent", FFI.errno) end @signaled = true end - + # Synonym for Event#reset if +bool+ is false, or Event#set # if +bool+ is true. - # + # def signaled=(bool) if bool set else reset end - end + end end end