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 +10 -5
- data/MANIFEST +9 -11
- data/README +39 -80
- data/Rakefile +9 -1
- data/examples/example_create.rb +35 -35
- data/examples/example_kill.rb +34 -34
- data/lib/win32/process/constants.rb +105 -0
- data/lib/win32/process/functions.rb +66 -0
- data/lib/win32/process/helper.rb +13 -0
- data/lib/win32/process/structs.rb +103 -0
- data/lib/win32/process.rb +751 -1013
- data/test/test_win32_process.rb +114 -88
- data/test/test_win32_process_kill.rb +144 -0
- data/win32-process.gemspec +7 -8
- metadata +17 -30
- data/examples/example_fork_wait.rb +0 -29
- data/examples/example_fork_waitpid.rb +0 -46
data/CHANGES
CHANGED
@@ -1,8 +1,13 @@
|
|
1
|
-
= 0.
|
2
|
-
*
|
3
|
-
|
4
|
-
|
5
|
-
|
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/
|
8
|
-
*
|
9
|
-
*
|
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
|
3
|
-
for MS Windows.
|
4
|
-
|
5
|
-
|
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
|
-
*
|
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.
|
23
|
-
3.times{
|
24
|
-
puts 'In the child'
|
25
|
-
sleep 1
|
26
|
-
}
|
27
|
-
}
|
20
|
+
p Process.job? # => true or false
|
28
21
|
|
29
|
-
Process.
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
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
|
-
|
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
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
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
|
-
|
71
|
-
|
72
|
-
it
|
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
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
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
|
-
|
81
|
-
|
82
|
-
|
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
|
94
|
-
|
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-
|
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
|
data/examples/example_create.rb
CHANGED
@@ -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
|
data/examples/example_kill.rb
CHANGED
@@ -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
|