win32-process 0.6.6 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -1,8 +1,13 @@
1
- = 0.6.6 - 19-Jul-2012
2
- * Fixed a param bug in the Process.fork method caused by a prototype change
3
- in the Windows::Process library of the windows-pr gem. Thanks go to
4
- mzverev for the spot.
5
- * Updated the gemspec, including updates to the windows-pr dependency.
1
+ = 0.7.0 - 22-Aug-2012
2
+ * Converted to use FFI instead of win32-api.
3
+ * Now requires Ruby 1.9.x or later.
4
+ * Removed the experimental Process.fork function. This obviated the necessity
5
+ of custom implementations of other methods, like Process.waitpid, so those
6
+ no longer have custom implementations either. These also proved to be
7
+ somewhat problematic with Ruby 1.9.x anyway.
8
+ * Removed the custom Process.ppid method because Ruby 1.9.x now supports it.
9
+ * The Process.kill method now supports the :exit_proc, :dll_module and
10
+ :wait_time options for signals 1 and 4-8.
6
11
 
7
12
  = 0.6.5 - 27-Dec-2010
8
13
  * Fixed getpriority and setpriority so that the underlying process handle is
data/MANIFEST CHANGED
@@ -1,11 +1,9 @@
1
- * CHANGES
2
- * README
3
- * MANIFEST
4
- * Rakefile
5
- * win32-process.gemspec
6
- * examples/example_create.rb
7
- * examples/example_fork_wait.rb
8
- * examples/example_fork_waitpid.rb
9
- * examples/example_kill.rb
10
- * lib/win32/process.rb
11
- * test/test_process.rb
1
+ * CHANGES
2
+ * README
3
+ * MANIFEST
4
+ * Rakefile
5
+ * win32-process.gemspec
6
+ * examples/example_create.rb
7
+ * examples/example_kill.rb
8
+ * lib/win32/process.rb
9
+ * test/test_process.rb
data/README CHANGED
@@ -1,12 +1,10 @@
1
1
  = Description
2
- This library provides the fork, wait, wait2, waitpid, and waitpid2 methods
3
- for MS Windows. In addition, it provides a different implementation of the
4
- kill method, a proper implementation of Process.ppid, and decent analogues
5
- of Process.getpriority, Process.setpriority, Process.getrlimit and
6
- Process.setrlimit.
7
-
2
+ This library provides analogues of the :getpriority, :setpriority, :getrlimit,
3
+ :setrlimit and :uid methods for MS Windows. It also adds the new methods :job?,
4
+ :get_affinity, and :create, and redefines the :kill method.
5
+
8
6
  = Prerequisites
9
- * windows-pr
7
+ * ffi
10
8
  * sys-proctable (dev only)
11
9
  * test-unit 2 (dev only)
12
10
 
@@ -19,92 +17,53 @@
19
17
  = Synopsis
20
18
  require 'win32/process'
21
19
 
22
- Process.fork{
23
- 3.times{
24
- puts 'In the child'
25
- sleep 1
26
- }
27
- }
20
+ p Process.job? # => true or false
28
21
 
29
- Process.wait
30
- puts 'Done'
31
-
32
- = Developer's Notes
33
- == The Process.fork and Process.wait methods
34
- The fork method is emulated on Windows by spawning another Ruby process
35
- against $PROGRAM_NAME via the CreateProcess() Win32 API function. It will
36
- use its parent's environment and starting directory.
37
-
38
- The various wait methods are a wrapper for the WaitForSingleObject() or
39
- WaitForMultipleObjects() Win32 API functions, for the wait* and waitpid*
40
- methods, respectively. In the case of wait2 and waitpid2, the exit value
41
- is returned via the GetExitCodeProcess() Win32API function.
42
-
43
- For now the waitpid and waitpid2 calls do not accept a second argument.
44
- That's because we haven't yet determined if there's a signal we should
45
- allow to be sent.
22
+ info = Process.create(
23
+ :app_name => "notepad.exe",
24
+ :creation_flags => Process::DETACHED_PROCESS,
25
+ :process_inherit => false,
26
+ :thread_inherit => true,
27
+ :cwd => "C:\\"
28
+ )
46
29
 
47
- IMPORTANT!
48
- Note that because fork is calling CreateProcess($PROGRAM_NAME), it will
49
- start again from the top of the script instead of from the point of the
50
- call. We will try to address this in a future release, if possible.
30
+ p info.process_id
51
31
 
52
- == The Process.kill method
53
- Initially, the kill method will try to get a HANDLE on the PID using the
54
- OpenProcess() function. If that succeeds, we know the process is running.
55
-
56
- In the event of signal 2 or signal 3, the GenerateConsoleCtrlEvent()
57
- function is used to send a signal to that process. These will not kill
58
- GUI processes. It will not (currently) send a signal to remote
59
- processes.
60
-
61
- In the event of signal 1 or 4-8, the CreateRemoteThread() function is used
62
- after the HANDLE's process has been identified to create a thread
63
- within that process. The ExitProcess() function is then sent to that
64
- thread.
65
-
66
- In the event of signal 9, the TerminateProcess() function is called. This
67
- will almost certainly kill the process, but doesn't give the process a
68
- chance to necessarily do any cleanup it might otherwise do.
32
+ = Developer's Notes
33
+ == Removal of Process.fork in release 0.7.0
34
+ The Process.fork method was originally experimental but it has never
35
+ been particularly useful in practice. On top of that, it required special
36
+ implementations of the Process.waitXXX methods, so it was a maintenance
37
+ issue as well.
69
38
 
70
- == The Process.ppid method
71
- In MRI the Process.ppid always returns 0 on MS Windows. With this library
72
- it returns the actual parent pid.
39
+ With Ruby 1.9 now becoming standard and its addition of Process.spawn
40
+ and friends (and concomitant support for the Process.waitXXX methods) I
41
+ felt it was time to remove it.
73
42
 
74
- == Differences between Ruby's kill and the Win32 Utils kill
75
- Ruby does not currently use the CreateRemoteThread() + ExitProcess()
76
- approach which is, according to everything I've read, a cleaner approach.
77
- This includes not only online research but also Jeffrey Richter's
78
- "Advanced Windows Programming, 3rd Edition."
43
+ You can still simulate Process.fork if you like using Process.create, which
44
+ is how it was implemented internally anyway. A better solution might be
45
+ to follow in the footsteps of ActiveState Perl, which uses native threads
46
+ to simulate fork on Windows.
79
47
 
80
- Also, the way Process.kill handles multiple pids works slightly differently
81
- (and better IMHO) in the Win32 Utils version than the way Ruby currently
82
- provides.
48
+ == Changes in the custom Process.kill method for 0.7.0
49
+ The Process.kill method in 0.7.0 more closely matches the spec now, but
50
+ the internal method for killing processes is still nicer for most signals.
51
+ With the release of 0.7.0 users can now specify options that provide finer
52
+ control over how a process is killed. See the documentation for details.
53
+
54
+ == The removal of the custom Process.ppid method
55
+ This was added at some point in the Ruby 1.9 dev cycle so it was removed
56
+ from this library.
83
57
 
84
- The reason Process.kill was originally added, in case anyone cares for
85
- historical trivia, is that Ruby 1.6.x did not support Process.kill on
86
- Windows at all.
87
-
88
- = Notes
89
- It is unlikely you will be able to kill system processes with this module.
90
- It's probably better that you don't.
91
-
92
58
  = Known Bugs
93
- None known (though please see the +Details+ section for quirks). Any
94
- bugs should be reported on the project page at
95
- http://rubyforge.org/projects/win32utils.
96
-
97
- = Future Plans
98
- Train Process.fork to execute from the point of the call rather than the
99
- top of the script (if possible).
100
-
101
- Other suggestions welcome.
59
+ None known. Any bugs should be reported on the project page at
60
+ https://github.com/djberg96/win32-process.
102
61
 
103
62
  = License
104
63
  Artistic 2.0
105
64
 
106
65
  = Copyright
107
- (C) 2003-2011 Daniel J. Berger
66
+ (C) 2003-2012 Daniel J. Berger
108
67
  All Rights Reserved
109
68
 
110
69
  = Warranty
data/Rakefile CHANGED
@@ -4,7 +4,7 @@ require 'rake/testtask'
4
4
  require 'rbconfig'
5
5
  include RbConfig
6
6
 
7
- CLEAN.include('**/*.gem', '**/*.rbc')
7
+ CLEAN.include('**/*.gem', '**/*.rbc', '**/*.log')
8
8
 
9
9
  namespace :gem do
10
10
  desc 'Create the win32-process gem'
@@ -42,6 +42,14 @@ namespace :example do
42
42
  end
43
43
  end
44
44
 
45
+ namespace :test do
46
+ Rake::TestTask.new(:kill) do |t|
47
+ t.verbose = true
48
+ t.warning = true
49
+ t.test_files = FileList['test/test_win32_process_kill.rb']
50
+ end
51
+ end
52
+
45
53
  Rake::TestTask.new do |t|
46
54
  t.verbose = true
47
55
  t.warning = true
@@ -1,35 +1,35 @@
1
- ##########################################################################
2
- # example_create.rb
3
- #
4
- # Simple test program for the Process.create() method. You can run this
5
- # code via the 'example:create' task.
6
- ##########################################################################
7
- require "win32/process"
8
-
9
- p Process::WIN32_PROCESS_VERSION
10
-
11
- struct = Process.create(
12
- :app_name => "notepad.exe",
13
- :creation_flags => Process::DETACHED_PROCESS,
14
- :process_inherit => false,
15
- :thread_inherit => true,
16
- :cwd => "C:\\",
17
- :inherit => true,
18
- :environment => "SYSTEMROOT=#{ENV['SYSTEMROOT']};PATH=C:\\"
19
- )
20
-
21
- p struct
22
-
23
- =begin
24
- # Don't run this from an existing terminal
25
- pid = Process.create(
26
- :app_name => "cmd.exe",
27
- :creation_flags => Process::DETACHED_PROCESS,
28
- :startf_flags => Process::USEPOSITION,
29
- :x => 0,
30
- :y => 0,
31
- :title => "Hi Dan"
32
- )
33
-
34
- puts "Pid of new process: #{pid}"
35
- =end
1
+ ##########################################################################
2
+ # example_create.rb
3
+ #
4
+ # Simple test program for the Process.create() method. You can run this
5
+ # code via the 'example:create' task.
6
+ ##########################################################################
7
+ require "win32/process"
8
+
9
+ p Process::WIN32_PROCESS_VERSION
10
+
11
+ struct = Process.create(
12
+ :app_name => "notepad.exe",
13
+ :creation_flags => Process::DETACHED_PROCESS,
14
+ :process_inherit => false,
15
+ :thread_inherit => true,
16
+ :cwd => "C:\\",
17
+ :inherit => true,
18
+ :environment => "SYSTEMROOT=#{ENV['SYSTEMROOT']};PATH=C:\\"
19
+ )
20
+
21
+ p struct
22
+
23
+ =begin
24
+ # Don't run this from an existing terminal
25
+ pid = Process.create(
26
+ :app_name => "cmd.exe",
27
+ :creation_flags => Process::DETACHED_PROCESS,
28
+ :startf_flags => Process::USEPOSITION,
29
+ :x => 0,
30
+ :y => 0,
31
+ :title => "Hi Dan"
32
+ )
33
+
34
+ puts "Pid of new process: #{pid}"
35
+ =end
@@ -1,34 +1,34 @@
1
- ##########################################################################
2
- # example_kill.rb
3
- #
4
- # Generic test script for futzing around Process.kill. This script
5
- # requires the sys-proctable library.
6
- #
7
- # You can run this example via the 'example:kill' task.
8
- ##########################################################################
9
- require "win32/process"
10
-
11
- begin
12
- require "sys/proctable"
13
- rescue LoadError
14
- STDERR.puts "Whoa there!"
15
- STDERR.puts "This script requires the sys-proctable package to work."
16
- STDERR.puts "You can find it at http://ruby-sysutils.sf.net"
17
- STDERR.puts "Exiting..."
18
- exit
19
- end
20
-
21
- include Sys
22
-
23
- puts "VERSION: " + Process::WIN32_PROCESS_VERSION
24
-
25
- IO.popen("notepad")
26
- sleep 1 # Give it a chance to start before checking for its pid
27
-
28
- pids = []
29
-
30
- ProcTable.ps{ |s|
31
- pids.push(s.pid) if s.cmdline =~ /notepad/i
32
- }
33
-
34
- p Process.kill(9,pids.last)
1
+ ##########################################################################
2
+ # example_kill.rb
3
+ #
4
+ # Generic test script for futzing around Process.kill. This script
5
+ # requires the sys-proctable library.
6
+ #
7
+ # You can run this example via the 'example:kill' task.
8
+ ##########################################################################
9
+ require "win32/process"
10
+
11
+ begin
12
+ require "sys/proctable"
13
+ rescue LoadError
14
+ STDERR.puts "Whoa there!"
15
+ STDERR.puts "This script requires the sys-proctable package to work."
16
+ STDERR.puts "You can find it at http://ruby-sysutils.sf.net"
17
+ STDERR.puts "Exiting..."
18
+ exit
19
+ end
20
+
21
+ include Sys
22
+
23
+ puts "VERSION: " + Process::WIN32_PROCESS_VERSION
24
+
25
+ IO.popen("notepad")
26
+ sleep 1 # Give it a chance to start before checking for its pid
27
+
28
+ pids = []
29
+
30
+ ProcTable.ps{ |s|
31
+ pids.push(s.pid) if s.cmdline =~ /notepad/i
32
+ }
33
+
34
+ p Process.kill(9,pids.last)
@@ -0,0 +1,105 @@
1
+ module Process::Constants
2
+ private
3
+
4
+ # Priority constants
5
+
6
+ ABOVE_NORMAL_PRIORITY_CLASS = 0x0008000
7
+ BELOW_NORMAL_PRIORITY_CLASS = 0x0004000
8
+ HIGH_PRIORITY_CLASS = 0x0000080
9
+ IDLE_PRIORITY_CLASS = 0x0000040
10
+ NORMAL_PRIORITY_CLASS = 0x0000020
11
+ REALTIME_PRIORITY_CLASS = 0x0000010
12
+
13
+ # Error constants
14
+
15
+ INVALID_HANDLE_VALUE = 0xffffffff
16
+ ERROR_ACCESS_DENIED = 0x00000005
17
+
18
+ # Process Access Rights
19
+
20
+ PROCESS_TERMINATE = 0x00000001
21
+ PROCESS_SET_INFORMATION = 0x00000200
22
+ PROCESS_QUERY_INFORMATION = 0x00000400
23
+ PROCESS_ALL_ACCESS = 0x001F0FFF
24
+ PROCESS_VM_READ = 0x00000010
25
+
26
+ # Process wait time for Process.kill
27
+
28
+ INFINITE = 0xFFFFFFFF
29
+
30
+ # Process creation flags
31
+
32
+ CREATE_BREAKAWAY_FROM_JOB = 0x01000000
33
+ CREATE_DEFAULT_ERROR_MODE = 0x04000000
34
+ CREATE_NEW_CONSOLE = 0x00000010
35
+ CREATE_NEW_PROCESS_GROUP = 0x00000200
36
+ CREATE_NO_WINDOW = 0x08000000
37
+ CREATE_PROTECTED_PROCESS = 0x00040000
38
+ CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000
39
+ CREATE_SEPARATE_WOW_VDM = 0x00000800
40
+ CREATE_SHARED_WOW_VDM = 0x00001000
41
+ CREATE_SUSPENDED = 0x00000004
42
+ CREATE_UNICODE_ENVIRONMENT = 0x00000400
43
+ DEBUG_ONLY_THIS_PROCESS = 0x00000002
44
+ DEBUG_PROCESS = 0x00000001
45
+ DETACHED_PROCESS = 0x00000008
46
+ INHERIT_PARENT_AFFINITY = 0x00010000
47
+
48
+ STARTF_USESHOWWINDOW = 0x00000001
49
+ STARTF_USESIZE = 0x00000002
50
+ STARTF_USEPOSITION = 0x00000004
51
+ STARTF_USECOUNTCHARS = 0x00000008
52
+ STARTF_USEFILLATTRIBUTE = 0x00000010
53
+ STARTF_RUNFULLSCREEN = 0x00000020
54
+ STARTF_FORCEONFEEDBACK = 0x00000040
55
+ STARTF_FORCEOFFFEEDBACK = 0x00000080
56
+ STARTF_USESTDHANDLES = 0x00000100
57
+ STARTF_USEHOTKEY = 0x00000200
58
+ STARTF_TITLEISLINKNAME = 0x00000800
59
+ STARTF_TITLEISAPPID = 0x00001000
60
+ STARTF_PREVENTPINNING = 0x00002000
61
+
62
+ LOGON_WITH_PROFILE = 0x00000001
63
+ LOGON_NETCREDENTIALS_ONLY = 0x00000002
64
+
65
+ SHUTDOWN_NORETRY = 0x00000001
66
+
67
+ # Security
68
+
69
+ TokenUser = 1
70
+ TOKEN_QUERY = 0x00000008
71
+
72
+ # Define these for Windows. They are not actually used but are defined
73
+ # for interface compatibility.
74
+
75
+ PRIO_PROCESS = 0
76
+ PRIO_PGRP = 1
77
+ PRIO_USER = 2
78
+
79
+ # Define these for Windows
80
+
81
+ RLIMIT_CPU = 0 # PerProcessUserTimeLimit
82
+ RLIMIT_FSIZE = 1 # Hard coded at 4TB - 64K (assumes NTFS)
83
+ RLIMIT_AS = 5 # ProcessMemoryLimit
84
+ RLIMIT_RSS = 5 # ProcessMemoryLimit
85
+ RLIMIT_VMEM = 5 # ProcessMemoryLimit
86
+
87
+ # Job constants
88
+
89
+ JOB_OBJECT_SET_ATTRIBUTES = 0x00000002
90
+ JOB_OBJECT_QUERY = 0x00000004
91
+ JOB_OBJECT_LIMIT_PROCESS_TIME = 0x00000002
92
+ JOB_OBJECT_LIMIT_PROCESS_MEMORY = 0x00000100
93
+ JobObjectExtendedLimitInformation = 9
94
+
95
+ # Console Events
96
+
97
+ CTRL_C_EVENT = 0
98
+ CTRL_BREAK_EVENT = 1
99
+
100
+ # Miscellaneous
101
+
102
+ HANDLE_FLAG_INHERIT = 0x00000001
103
+ SEM_FAILCRITICALERRORS = 0x00000001
104
+ SEM_NOGPFAULTERRORBOX = 0x00000002
105
+ end
@@ -0,0 +1,66 @@
1
+ if RUBY_PLATFORM == 'java'
2
+ require 'rubygems'
3
+ gem 'ffi'
4
+ end
5
+
6
+ require 'ffi'
7
+
8
+ module Process::Functions
9
+ module FFI::Library
10
+ # Wrapper method for attach_function + private
11
+ def attach_pfunc(*args)
12
+ attach_function(*args)
13
+ private args[0]
14
+ end
15
+ end
16
+
17
+ extend FFI::Library
18
+
19
+ ffi_lib :kernel32
20
+
21
+ attach_pfunc :CloseHandle, [:ulong], :bool
22
+ attach_pfunc :GenerateConsoleCtrlEvent, [:ulong, :ulong], :bool
23
+ attach_pfunc :GetCurrentProcess, [], :ulong
24
+ attach_pfunc :GetModuleHandle, :GetModuleHandleA, [:string], :ulong
25
+ attach_pfunc :GetProcessAffinityMask, [:ulong, :pointer, :pointer], :bool
26
+ attach_pfunc :GetPriorityClass, [:ulong], :ulong
27
+ attach_pfunc :GetProcAddress, [:ulong, :string], :ulong
28
+ attach_pfunc :IsProcessInJob, [:ulong, :pointer, :pointer], :void
29
+ attach_pfunc :OpenProcess, [:ulong, :bool, :ulong], :ulong
30
+ attach_pfunc :SetHandleInformation, [:ulong, :ulong, :ulong], :bool
31
+ attach_pfunc :SetErrorMode, [:uint], :uint
32
+ attach_pfunc :SetPriorityClass, [:ulong, :ulong], :bool
33
+ attach_pfunc :TerminateProcess, [:ulong, :uint], :bool
34
+ attach_pfunc :WaitForSingleObject, [:ulong, :ulong], :ulong
35
+
36
+ attach_pfunc :CreateRemoteThread,
37
+ [:ulong, :pointer, :size_t, :ulong, :pointer, :ulong, :pointer], :ulong
38
+
39
+ attach_pfunc :GetVolumeInformationA,
40
+ [:string, :pointer, :ulong, :pointer, :pointer, :pointer, :pointer, :ulong], :bool
41
+
42
+ attach_pfunc :CreateProcessW,
43
+ [:buffer_in, :buffer_in, :pointer, :pointer, :bool,
44
+ :ulong, :buffer_in, :buffer_in, :pointer, :pointer], :bool
45
+
46
+ attach_pfunc :AssignProcessToJobObject, [:ulong, :ulong], :bool
47
+ attach_pfunc :CreateJobObjectA, [:pointer, :string], :ulong
48
+ attach_pfunc :OpenJobObjectA, [:ulong, :bool, :string], :ulong
49
+ attach_pfunc :QueryInformationJobObject, [:ulong, :int, :pointer, :ulong, :pointer], :bool
50
+ attach_pfunc :SetInformationJobObject, [:ulong, :int, :pointer, :ulong], :bool
51
+
52
+ ffi_lib :advapi32
53
+
54
+ attach_pfunc :ConvertSidToStringSidA, [:buffer_in, :pointer], :bool
55
+ attach_pfunc :GetTokenInformation, [:ulong, :int, :pointer, :ulong, :pointer], :bool
56
+ attach_pfunc :OpenProcessToken, [:ulong, :ulong, :pointer], :bool
57
+
58
+ attach_pfunc :CreateProcessWithLogonW,
59
+ [:buffer_in, :buffer_in, :buffer_in, :ulong, :buffer_in, :buffer_in,
60
+ :ulong, :buffer_in, :buffer_in, :pointer, :pointer], :bool
61
+
62
+ ffi_lib FFI::Library::LIBC
63
+
64
+ attach_pfunc :get_errno, :_get_errno, [:pointer], :int
65
+ attach_pfunc :get_osfhandle, :_get_osfhandle, [:int], :ulong
66
+ end
@@ -0,0 +1,13 @@
1
+ class String
2
+ # Convert a regular string to a wide character string. This does not
3
+ # modify the receiver.
4
+ def to_wide_string
5
+ (self + 0.chr).encode('UTF-16LE')
6
+ end
7
+
8
+ # Convert a regular string to a wide character string. This modifies
9
+ # the receiver.
10
+ def to_wide_string!
11
+ replace((self + 0.chr).encode('UTF-16LE'))
12
+ end
13
+ end
@@ -0,0 +1,103 @@
1
+ if RUBY_PLATFORM == 'java'
2
+ require 'rubygems'
3
+ gem 'ffi'
4
+ end
5
+
6
+ require 'ffi'
7
+
8
+ module Process::Structs
9
+ extend FFI::Library
10
+
11
+ private
12
+
13
+ # sizeof(LARGE_INTEGER) == 8
14
+ class LARGE_INTEGER < FFI::Union
15
+ layout(:QuadPart, :long_long)
16
+ end
17
+
18
+ # sizeof(IO_COUNTERS) == 48
19
+ class IO_COUNTERS < FFI::Struct
20
+ layout(
21
+ :ReadOperationCount, :ulong_long,
22
+ :WriteOperationCount, :ulong_long,
23
+ :OtherOperationCount, :ulong_long,
24
+ :ReadTransferCount, :ulong_long,
25
+ :WriteTransferCount, :ulong_long,
26
+ :OtherTransferCount, :ulong_long
27
+ )
28
+ end
29
+
30
+ class JOBJECT_BASIC_LIMIT_INFORMATION < FFI::Struct
31
+ layout(
32
+ :PerProcessUserTimeLimit, LARGE_INTEGER,
33
+ :PerJobUserTimeLimit, LARGE_INTEGER,
34
+ :LimitFlags, :ulong,
35
+ :MinimumWorkingSetSize, :size_t,
36
+ :MaximumWorkingSetSize, :size_t,
37
+ :ActiveProcessLimit, :ulong,
38
+ :Affinity, :pointer,
39
+ :PriorityClass, :ulong,
40
+ :SchedulingClass, :ulong
41
+ )
42
+ end
43
+
44
+ class JOBJECT_EXTENDED_LIMIT_INFORMATION < FFI::Struct
45
+ layout(
46
+ :BasicLimitInformation, JOBJECT_BASIC_LIMIT_INFORMATION,
47
+ :IoInfo, IO_COUNTERS,
48
+ :ProcessMemoryLimit, :size_t,
49
+ :JobMemoryLimit, :size_t,
50
+ :PeakProcessMemoryUsed, :size_t,
51
+ :PeakJobMemoryUsed, :size_t
52
+ )
53
+ end
54
+
55
+ class SECURITY_ATTRIBUTES < FFI::Struct
56
+ layout(
57
+ :nLength, :ulong,
58
+ :lpSecurityDescriptor, :pointer,
59
+ :bInheritHandle, :bool
60
+ )
61
+ end
62
+
63
+ # sizeof(STARTUPINFO) == 68
64
+ class STARTUPINFO < FFI::Struct
65
+ layout(
66
+ :cb, :ulong,
67
+ :lpReserved, :string,
68
+ :lpDesktop, :string,
69
+ :lpTitle, :string,
70
+ :dwX, :ulong,
71
+ :dwY, :ulong,
72
+ :dwXSize, :ulong,
73
+ :dwYSize, :ulong,
74
+ :dwXCountChars, :ulong,
75
+ :dwYCountChars, :ulong,
76
+ :dwFillAttribute, :ulong,
77
+ :dwFlags, :ulong,
78
+ :wShowWindow, :short,
79
+ :cbReserved2, :short,
80
+ :lpReserved2, :pointer,
81
+ :hStdInput, :ulong,
82
+ :hStdOutput, :ulong,
83
+ :hStdError, :ulong
84
+ )
85
+ end
86
+
87
+ class PROCESS_INFORMATION < FFI::Struct
88
+ layout(
89
+ :hProcess, :ulong,
90
+ :hThread, :ulong,
91
+ :dwProcessId, :ulong,
92
+ :dwThreadId, :ulong
93
+ )
94
+ end
95
+
96
+ # Used by Process.create
97
+ ProcessInfo = Struct.new("ProcessInfo",
98
+ :process_handle,
99
+ :thread_handle,
100
+ :process_id,
101
+ :thread_id
102
+ )
103
+ end