win32-process 0.6.6 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|