Module: ChildProcess::Windows::Lib

Extended by:
FFI::Library
Defined in:
lib/childprocess/windows.rb,
lib/childprocess/windows/constants.rb,
lib/childprocess/windows/functions.rb

Class Method Summary collapse

Class Method Details

.create_proc(cmd, opts = {}) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/childprocess/windows/functions.rb', line 5

def self.create_proc(cmd, opts = {})
  cmd_ptr = FFI::MemoryPointer.from_string cmd

  flags   = 0
  inherit = !!opts[:inherit]

  flags |= DETACHED_PROCESS if opts[:detach]

  si = StartupInfo.new
  pi = ProcessInfo.new

  if opts[:stdout] || opts[:stderr]
    si[:dwFlags] ||= 0
    si[:dwFlags] |= STARTF_USESTDHANDLES
    inherit = true

    si[:hStdOutput] = get_os_file_handle(opts[:stdout].fileno) if opts[:stdout]
    si[:hStdError]  = get_os_file_handle(opts[:stderr].fileno) if opts[:stderr]
  end

  ok = create_process(nil, cmd_ptr, nil, nil, inherit, flags, nil, nil, si, pi)
  ok or raise Error, last_error_message

  close_handle pi[:hProcess]
  close_handle pi[:hThread]

  pi[:dwProcessId]
end

.get_os_file_handle(fd_or_io) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/childprocess/windows/functions.rb', line 46

def self.get_os_file_handle(fd_or_io)
  case fd_or_io
  when IO
    handle = _get_osfhandle(fd.fileno)
  when Fixnum
    handle = _get_osfhandle(fd_or_io)
  else
    if fd_or_io.respond_to?(:to_io)
      io = fd_or_io.to_io

      unless io.kind_of?(IO)
        raise TypeError, "expected #to_io to return an instance of IO"
      end

      handle = _get_osfhandle(io.fileno)
    else
      raise TypeError, "invalid type: #{fd_or_io.inspect}"
    end
  end

  if handle == INVALID_HANDLE_VALUE
    raise Error, Lib.last_error_message
  end

  handle
end

.last_error_messageObject



34
35
36
37
38
39
40
41
42
43
44
# File 'lib/childprocess/windows/functions.rb', line 34

def self.last_error_message
  errnum = get_last_error
  buf = FFI::MemoryPointer.new :char, 512

  size = format_message(
    FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
    nil, errnum, 0, buf, buf.size, nil
  )

  buf.read_string(size).strip
end

.msvcrt_nameObject



9
10
11
12
13
14
15
16
17
18
# File 'lib/childprocess/windows.rb', line 9

def self.msvcrt_name
  host_part = RbConfig::CONFIG['host_os'].split("_")[1]
  manifest  = File.join(RbConfig::CONFIG['bindir'], 'ruby.exe.manifest')

  if host_part && host_part.to_i > 80 && File.exists?(manifest)
    "msvcr#{host_part}"
  else
    "msvcrt"
  end
end