vrvirtualdesktop 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +4 -0
- data/LICENSE +1 -0
- data/README +37 -0
- data/TODO +3 -0
- data/bin/vrdesk.rbw +55 -0
- data/lib/VRVirtualDesktopForm.rb +267 -0
- data/lib/Win32/APIMapper.rb +62 -0
- data/lib/Win32/Base-consts.rb +891 -0
- data/lib/Win32/Base.rb +275 -0
- data/lib/Win32/Encoding.rb +68 -0
- data/lib/Win32/GetSystemMetrics.rb +107 -0
- data/lib/Win32/NetResources.rb +160 -0
- data/lib/Win32/Process.rb +468 -0
- data/lib/Win32/Registry.rb +515 -0
- data/lib/Win32/User32.rb +142 -0
- data/lib/Win32/VirtualDesktop.rb +418 -0
- data/lib/Win32/WindowManager.rb +177 -0
- data/lib/resources/desktops.ico +0 -0
- data/lib/resources/five_down.ico +0 -0
- data/lib/resources/five_up.ico +0 -0
- data/lib/resources/four_down.ico +0 -0
- data/lib/resources/four_up.ico +0 -0
- data/lib/resources/obdb.ico +0 -0
- data/lib/resources/one_down.ico +0 -0
- data/lib/resources/one_up.ico +0 -0
- data/lib/resources/six_down.ico +0 -0
- data/lib/resources/six_up.ico +0 -0
- data/lib/resources/three_down.ico +0 -0
- data/lib/resources/three_up.ico +0 -0
- data/lib/resources/two_down.ico +0 -0
- data/lib/resources/two_up.ico +0 -0
- metadata +97 -0
@@ -0,0 +1,160 @@
|
|
1
|
+
##################################################################################################
|
2
|
+
#
|
3
|
+
# $Author: Steve $
|
4
|
+
# $Date: 2005/12/16 18:35:42 $
|
5
|
+
# $Version: 0.99 $
|
6
|
+
# $Change: $
|
7
|
+
#
|
8
|
+
##################################################################################################
|
9
|
+
|
10
|
+
#-------------------------------------------------------------------------------------------------
|
11
|
+
# This module mounts SAMBA (Win32) network resources
|
12
|
+
module Win32
|
13
|
+
|
14
|
+
module NetResources
|
15
|
+
|
16
|
+
require 'win32ole'
|
17
|
+
|
18
|
+
#-----------------------------------------------------------------------------------------
|
19
|
+
#-----------------------------------------------------------------------------------------
|
20
|
+
# Exceptions
|
21
|
+
class Error < StandardError
|
22
|
+
#-------------------------------------------------------------------------------------
|
23
|
+
# attributesFor: "description"
|
24
|
+
attr_reader :errno, :error, :OLEObject, :OLEMethod
|
25
|
+
|
26
|
+
#-------------------------------------------------------------------------------------
|
27
|
+
# class methodsFor: "initialization"
|
28
|
+
def initialize(p_e)
|
29
|
+
bInOLE = false
|
30
|
+
@errno = 0
|
31
|
+
@error = ''
|
32
|
+
p_e.to_s.each do |line|
|
33
|
+
case line.chomp
|
34
|
+
when /^\s*OLE error code:([0-9a-hA-H]+) in (\w+)\.(\w+)/
|
35
|
+
@errno = $1.hex
|
36
|
+
@OLEObject = $2
|
37
|
+
@OLEMethod = $3
|
38
|
+
bInOLE = true
|
39
|
+
when /^\s+(.*)/ then @error += $1 + "\n" if bInOLE
|
40
|
+
when /^$/ then bInOLE = false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
@error = @error.chomp
|
44
|
+
super("0x%X" % @errno + ": " + @error)
|
45
|
+
end
|
46
|
+
|
47
|
+
#-------------------------------------------------------------------------------------
|
48
|
+
# methodsFor: "accessing"
|
49
|
+
def to_i
|
50
|
+
return @errno
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
#-----------------------------------------------------------------------------------------
|
55
|
+
#-----------------------------------------------------------------------------------------
|
56
|
+
# methodsFor: "mounting/unmounting"
|
57
|
+
def NetResources.mount(
|
58
|
+
p_strLocal,
|
59
|
+
p_strRemote,
|
60
|
+
p_strUser = nil,
|
61
|
+
p_strPwd = nil,
|
62
|
+
p_bUpdate = false) # true if we want to update the local user's profile
|
63
|
+
begin
|
64
|
+
wsh = WIN32OLE.new('WScript.Network')
|
65
|
+
wsh.MapNetworkDrive(p_strLocal.gsub(/\w$/, '\0:'), p_strRemote.gsub(/\//, "\\"),
|
66
|
+
p_bUpdate, p_strUser, p_strPwd)
|
67
|
+
rescue WIN32OLERuntimeError => p_e
|
68
|
+
raise Error, p_e
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def NetResources.umount(p_strName, p_bForce = true, p_bUpdate = false)
|
73
|
+
begin
|
74
|
+
wsh = WIN32OLE.new('WScript.Network')
|
75
|
+
wsh.RemoveNetworkDrive(p_strName, p_bForce, p_bUpdate)
|
76
|
+
rescue WIN32OLERuntimeError => p_e
|
77
|
+
raise Error, p_e
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def NetResources.mountPrinter(
|
82
|
+
p_strLocal,
|
83
|
+
p_strRemote,
|
84
|
+
p_strUser = nil,
|
85
|
+
p_strPwd = nil,
|
86
|
+
p_bUpdate = false) # true if we want to update the local user's profile
|
87
|
+
begin
|
88
|
+
wsh = WIN32OLE.new('WScript.Network')
|
89
|
+
wsh.AddPrinterConnection(p_strLocal, p_strRemote.gsub(/\//, "\\"),
|
90
|
+
p_bUpdate, p_strUser, p_strPwd)
|
91
|
+
rescue WIN32OLERuntimeError => p_e
|
92
|
+
raise Error, p_e
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def NetResources.umountPrinter(p_strName, p_bForce = true, p_bUpdate = false)
|
97
|
+
begin
|
98
|
+
wsh = WIN32OLE.new('WScript.Network')
|
99
|
+
wsh.RemovePrinterConnection(p_strName, p_bForce, p_bUpdate)
|
100
|
+
rescue WIN32OLERuntimeError => p_e
|
101
|
+
raise Error, p_e
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
#-----------------------------------------------------------------------------------------
|
106
|
+
#-----------------------------------------------------------------------------------------
|
107
|
+
# methodsFor: "defaulting"
|
108
|
+
def NetResources.setDefaultPrinter(p_strName)
|
109
|
+
begin
|
110
|
+
wsh = WIN32OLE.new('WScript.Network')
|
111
|
+
wsh.SetDefaultPrinter(p_strName)
|
112
|
+
rescue WIN32OLERuntimeError => p_e
|
113
|
+
raise Error, p_e
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
#-----------------------------------------------------------------------------------------
|
118
|
+
#-----------------------------------------------------------------------------------------
|
119
|
+
# methodsFor: "enumerating"
|
120
|
+
def NetResources.mounts
|
121
|
+
begin
|
122
|
+
wsh = WIN32OLE.new('WScript.Network')
|
123
|
+
vValues = wsh.EnumNetworkDrives()
|
124
|
+
mRet = {}
|
125
|
+
key = nil
|
126
|
+
vValues.each do |item|
|
127
|
+
if key.nil? then key = item
|
128
|
+
else
|
129
|
+
mRet[key] = item
|
130
|
+
key = nil
|
131
|
+
end
|
132
|
+
end
|
133
|
+
rescue WIN32OLERuntimeError
|
134
|
+
raise Error, p_e
|
135
|
+
ensure
|
136
|
+
return mRet
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def NetResources.printers
|
141
|
+
begin
|
142
|
+
wsh = WIN32OLE.new('WScript.Network')
|
143
|
+
vValues = wsh.EnumPrinterConnections()
|
144
|
+
mRet = {}
|
145
|
+
key = nil
|
146
|
+
vValues.each do |item|
|
147
|
+
if key.nil? then key = item
|
148
|
+
else
|
149
|
+
mRet[key] = item
|
150
|
+
key = nil
|
151
|
+
end
|
152
|
+
end
|
153
|
+
rescue WIN32OLERuntimeError
|
154
|
+
raise Error, p_e
|
155
|
+
ensure
|
156
|
+
return mRet
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,468 @@
|
|
1
|
+
##################################################################################################
|
2
|
+
#
|
3
|
+
# $Author: Steve $
|
4
|
+
# $Date: 2005/12/16 18:35:42 $
|
5
|
+
# $Version: 0.99 $
|
6
|
+
# $Change: $
|
7
|
+
#
|
8
|
+
##################################################################################################
|
9
|
+
require "Win32/APIMapper"
|
10
|
+
|
11
|
+
module Win32
|
12
|
+
require 'Win32API'
|
13
|
+
|
14
|
+
#---------------------------------------------------------------------------------------------
|
15
|
+
#---------------------------------------------------------------------------------------------
|
16
|
+
# This class contains the process info created by Win32::Process
|
17
|
+
class ProcessInfo
|
18
|
+
#-----------------------------------------------------------------------------------------
|
19
|
+
# attributesFor: "process handles"
|
20
|
+
attr_reader :hProcess, :hThread, :pid, :tid # Thread Id
|
21
|
+
attr_writer :hProcess, :hThread, :pid, :tid # Thread Id
|
22
|
+
|
23
|
+
#-----------------------------------------------------------------------------------------
|
24
|
+
# class methodsFor: "Data sizing"
|
25
|
+
def ProcessInfo.sizeof
|
26
|
+
return 16 # 4 longs
|
27
|
+
end
|
28
|
+
|
29
|
+
#-----------------------------------------------------------------------------------------
|
30
|
+
# class methodsFor: "initialization"
|
31
|
+
def initialize(p_hProcess = nil, p_hThread = nil, p_pid = nil, p_tid = nil)
|
32
|
+
@hProcess = p_hProcess
|
33
|
+
@hThread = p_hThread
|
34
|
+
@pid = p_pid
|
35
|
+
@tid = p_tid
|
36
|
+
end
|
37
|
+
|
38
|
+
#-----------------------------------------------------------------------------------------
|
39
|
+
# class methodsFor: "unpacking data"
|
40
|
+
def ProcessInfo.unpack(p_pData)
|
41
|
+
pData = p_pData.unpack("L4")
|
42
|
+
return ProcessInfo.new(pData[0], pData[1], pData[2], pData[3])
|
43
|
+
end
|
44
|
+
|
45
|
+
#-----------------------------------------------------------------------------------------
|
46
|
+
# methodsFor: "packing data"
|
47
|
+
def pack
|
48
|
+
return [@hProcess, @hThread, @pid, @tid].pack("L*")
|
49
|
+
end
|
50
|
+
|
51
|
+
#-----------------------------------------------------------------------------------------
|
52
|
+
# methodsFor: "printing"
|
53
|
+
def to_s
|
54
|
+
return "hProcess: #{@hProcess}, hThread: #{@hThread}, pid: #{@pid}, thread id: #{@tid}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
#---------------------------------------------------------------------------------------------
|
59
|
+
#---------------------------------------------------------------------------------------------
|
60
|
+
# This class contains the startup info that is passed to Win32::Process.Create
|
61
|
+
# It tells how the process should be created and where it should appear
|
62
|
+
class StartupInfo
|
63
|
+
#-----------------------------------------------------------------------------------------
|
64
|
+
# attributesFor: "window properties"
|
65
|
+
attr_reader :desktop, :title, :x, :y, :width, :length, :xCountChars, :yCountChars,
|
66
|
+
:fillAttribute, :showWindow, :stdin, :stdout, :stderr
|
67
|
+
|
68
|
+
#-----------------------------------------------------------------------------------------
|
69
|
+
# constsFor: "Startup Information Flags"
|
70
|
+
# (from WinBase.h)
|
71
|
+
STARTF_USESHOWWINDOW = 0x00000001
|
72
|
+
STARTF_USESIZE = 0x00000002
|
73
|
+
STARTF_USEPOSITION = 0x00000004
|
74
|
+
STARTF_USECOUNTCHARS = 0x00000008
|
75
|
+
STARTF_USEFILLATTRIBUTE = 0x00000010
|
76
|
+
STARTF_RUNFULLSCREEN = 0x00000020
|
77
|
+
STARTF_FORCEONFEEDBACK = 0x00000040
|
78
|
+
STARTF_FORCEOFFFEEDBACK = 0x00000080
|
79
|
+
STARTF_USESTDHANDLES = 0x00000100
|
80
|
+
STARTF_USEHOTKEY = 0x00000200
|
81
|
+
FOREGROUND_BLUE = 0x0001
|
82
|
+
FOREGROUND_GREEN = 0x0002
|
83
|
+
FOREGROUND_RED = 0x0004
|
84
|
+
FOREGROUND_INTENSITY = 0x0008
|
85
|
+
BACKGROUND_BLUE = 0x0010
|
86
|
+
BACKGROUND_GREEN = 0x0020
|
87
|
+
BACKGROUND_RED = 0x0040
|
88
|
+
BACKGROUND_INTENSITY = 0x0080
|
89
|
+
|
90
|
+
#-----------------------------------------------------------------------------------------
|
91
|
+
# constsFor: "Show Window values"
|
92
|
+
# (from WinUser.h)
|
93
|
+
SW_HIDE = 0
|
94
|
+
SW_SHOWNORMAL = 1
|
95
|
+
SW_NORMAL = 1
|
96
|
+
SW_SHOWMINIMIZED = 2
|
97
|
+
SW_SHOWMAXIMIZED = 3
|
98
|
+
SW_MAXIMIZE = 3
|
99
|
+
SW_SHOWNOACTIVATE = 4
|
100
|
+
SW_SHOW = 5
|
101
|
+
SW_MINIMIZE = 6
|
102
|
+
SW_SHOWMINNOACTIVE = 7
|
103
|
+
SW_SHOWNA = 8
|
104
|
+
SW_RESTORE = 9
|
105
|
+
SW_SHOWDEFAULT = 10
|
106
|
+
SW_FORCEMINIMIZE = 11
|
107
|
+
SW_MAX = 11
|
108
|
+
|
109
|
+
#-----------------------------------------------------------------------------------------
|
110
|
+
# class methodsFor: "Data sizing"
|
111
|
+
def StartupInfo.sizeof
|
112
|
+
return 80 # 16 longs and 2 words
|
113
|
+
end
|
114
|
+
|
115
|
+
#-----------------------------------------------------------------------------------------
|
116
|
+
# class methodsFor: "initialization"
|
117
|
+
def initialize(
|
118
|
+
p_pDesktop = nil, p_strTitle = nil,
|
119
|
+
p_x = nil, p_y = nil, p_width = nil, p_length = nil,
|
120
|
+
p_xCountChars = nil, p_yCountChars = nil,
|
121
|
+
p_fillAttribute = nil,
|
122
|
+
p_showWindow = nil,
|
123
|
+
p_stdin = nil, p_stdout = nil, p_stderr = nil)
|
124
|
+
@desktop = p_pDesktop
|
125
|
+
@title = p_strTitle
|
126
|
+
@flags = 0
|
127
|
+
self.x = p_x
|
128
|
+
self.y = p_y
|
129
|
+
self.width = p_width
|
130
|
+
self.length = p_length
|
131
|
+
self.xCountChars = p_xCountChars
|
132
|
+
self.yCountChars = p_yCountChars
|
133
|
+
self.fillAttribute = p_fillAttribute
|
134
|
+
self.showWindow = p_showWindow
|
135
|
+
self.stdin = p_stdin
|
136
|
+
self.stdout = p_stdout
|
137
|
+
self.stderr = p_stderr
|
138
|
+
end
|
139
|
+
|
140
|
+
#-----------------------------------------------------------------------------------------
|
141
|
+
# class methodsFor: "unpacking data"
|
142
|
+
def StartupInfo.unpack(p_pData)
|
143
|
+
pData = p_pData.unpack("L12S2L4")
|
144
|
+
return StartupInfo.new(
|
145
|
+
pData[ 1], pData[ 2],
|
146
|
+
pData[ 3], pData[ 4], pData[ 5], pData[ 6],
|
147
|
+
pData[ 7], pData[ 8],
|
148
|
+
pData[ 9],
|
149
|
+
pData[11],
|
150
|
+
pData[14], pData[15], pData[16]
|
151
|
+
)
|
152
|
+
end
|
153
|
+
|
154
|
+
def xx(val)
|
155
|
+
if RUBY_VERSION >= "1.8.2" then
|
156
|
+
if val == nil then
|
157
|
+
0
|
158
|
+
else
|
159
|
+
val
|
160
|
+
end
|
161
|
+
else
|
162
|
+
val
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
#-----------------------------------------------------------------------------------------
|
167
|
+
# methodsFor: "packing data"
|
168
|
+
def pack
|
169
|
+
return [StartupInfo.sizeof,
|
170
|
+
0,
|
171
|
+
xx(@desktop),
|
172
|
+
xx(@title),
|
173
|
+
xx(@x), xx(@y), xx(@width), xx(@length),
|
174
|
+
xx(@xCountChars), xx(@yCountChars),
|
175
|
+
xx(@fillAttribute),
|
176
|
+
xx(@flags),
|
177
|
+
xx(@showWindow),
|
178
|
+
0, 0,
|
179
|
+
xx(@stdin), xx(@stdout), xx(@stderr)
|
180
|
+
].pack('L12S2L4')
|
181
|
+
end
|
182
|
+
|
183
|
+
#-----------------------------------------------------------------------------------------
|
184
|
+
# methodsFor: "accessing"
|
185
|
+
def x=(p_x)
|
186
|
+
condsetf(nil != (@x = p_x), STARTF_USEPOSITION)
|
187
|
+
end
|
188
|
+
|
189
|
+
def y=(p_y)
|
190
|
+
condsetf(nil != (@y = p_y), STARTF_USEPOSITION)
|
191
|
+
end
|
192
|
+
|
193
|
+
def width=(p_width)
|
194
|
+
condsetf(nil != (@width = p_width), STARTF_USESIZE)
|
195
|
+
end
|
196
|
+
|
197
|
+
def length=(p_length)
|
198
|
+
condsetf(nil != (@length = p_length), STARTF_USESIZE)
|
199
|
+
end
|
200
|
+
|
201
|
+
def xCountChars=(p_xCountChars)
|
202
|
+
condsetf(nil != (@xCountChars = p_xCountChars), STARTF_USECOUNTCHARS)
|
203
|
+
end
|
204
|
+
|
205
|
+
def yCountChars=(p_yCountChars)
|
206
|
+
condsetf(nil != (@yCountChars = p_yCountChars), STARTF_USECOUNTCHARS)
|
207
|
+
end
|
208
|
+
|
209
|
+
def fillAttribute=(p_fillAttribute)
|
210
|
+
condsetf(nil != (@fillAttribute = p_fillAttribute), STARTF_USEFILLATTRIBUTE)
|
211
|
+
end
|
212
|
+
|
213
|
+
def showWindow=(p_showWindow)
|
214
|
+
condsetf(nil != (@showWindow = p_showWindow), STARTF_USESHOWWINDOW)
|
215
|
+
end
|
216
|
+
|
217
|
+
def stdin=(p_stdin)
|
218
|
+
condsetf(nil != (@stdin = p_stdin), STARTF_USESTDHANDLES)
|
219
|
+
end
|
220
|
+
|
221
|
+
def stdout=(p_stdout)
|
222
|
+
condsetf(nil != (@stdout = p_stdout), STARTF_USESTDHANDLES)
|
223
|
+
end
|
224
|
+
|
225
|
+
def stderr=(p_stderr)
|
226
|
+
condsetf(nil != (@stderr = p_stderr), STARTF_USESTDHANDLES)
|
227
|
+
end
|
228
|
+
|
229
|
+
#-----------------------------------------------------------------------------------------
|
230
|
+
# methodsFor: "printing"
|
231
|
+
def to_s
|
232
|
+
str = "["
|
233
|
+
str += " desktop: #{@desktop}" if nil != @desktop
|
234
|
+
str += " title: #{@title}" if nil != @title
|
235
|
+
str += " x: #{@x} y: #{@y}" if testf(STARTF_USEPOSITION)
|
236
|
+
str += " width: #{@width} length: #{@length}" if testf(STARTF_USESIZE)
|
237
|
+
str += " xCountChars: #{@xCountChars} yCountChars: #{@yCountChars}" if testf(STARTF_USECOUNTCHARS)
|
238
|
+
str += " fillAttribute: #{@fillAttribute}" if testf(STARTF_USEFILLATTRIBUTE)
|
239
|
+
str += " showWindow: #{@showWindow}" if testf(STARTF_USESHOWWINDOW)
|
240
|
+
str += " stdin: #{@stdin} stdout: #{@stdout} stderr: #{@stderr}" if testf(STARTF_USESTDHANDLES)
|
241
|
+
str += " ]"
|
242
|
+
return str
|
243
|
+
end
|
244
|
+
|
245
|
+
#-----------------------------------------------------------------------------------------
|
246
|
+
private
|
247
|
+
|
248
|
+
#-----------------------------------------------------------------------------------------
|
249
|
+
# methodsFor: "flag conditions handling"
|
250
|
+
def condsetf(p_condition, p_flag)
|
251
|
+
p_condition ? setf(p_flag) : unsetf(p_flag)
|
252
|
+
end
|
253
|
+
|
254
|
+
def setf(p_flag)
|
255
|
+
@flags |= p_flag
|
256
|
+
end
|
257
|
+
|
258
|
+
def unsetf(p_flag)
|
259
|
+
@flags &= ~p_flag
|
260
|
+
end
|
261
|
+
|
262
|
+
def testf(p_flag)
|
263
|
+
return p_flag == (@flags & p_flag)
|
264
|
+
end
|
265
|
+
|
266
|
+
end
|
267
|
+
|
268
|
+
#---------------------------------------------------------------------------------------------
|
269
|
+
#---------------------------------------------------------------------------------------------
|
270
|
+
# This class creates a Windows process and can manipulate it.
|
271
|
+
class Process
|
272
|
+
|
273
|
+
#-----------------------------------------------------------------------------------------
|
274
|
+
# constsFor: "Wait Return Codes"
|
275
|
+
# (from WinUser.h)
|
276
|
+
WAIT_INFINITE = 0xFFFFFFFF
|
277
|
+
WAIT_FAILED = 0xFFFFFFFF
|
278
|
+
WAIT_OBJECT_0 = 0x00000000
|
279
|
+
WAIT_ABANDONED = 0x00000080
|
280
|
+
WAIT_IO_COMPLETION = 0x000000C0
|
281
|
+
WAIT_TIMEOUT = 0x00000102
|
282
|
+
|
283
|
+
#-----------------------------------------------------------------------------------------
|
284
|
+
include APIMapper
|
285
|
+
|
286
|
+
APIMapper.Initialize(
|
287
|
+
'CreateProcess' => {DLL => 'kernel32', NAME => 'CreateProcess',
|
288
|
+
IN => ['P'] * 4 + ['L', 'L'] + ['P'] * 4, OUT => 'L'},
|
289
|
+
'OpenProcess' => {DLL => 'kernel32', NAME => 'OpenProcess',
|
290
|
+
IN => ['L', 'L', 'L'], OUT => 'L'},
|
291
|
+
'TerminateProcess' => {DLL => 'kernel32', NAME => 'TerminateProcess',
|
292
|
+
IN => ['L', 'L'], OUT => 'L'},
|
293
|
+
'WaitForObject' => {DLL => 'kernel32', NAME => 'WaitForSingleObjectEx',
|
294
|
+
IN => ['L', 'L', 'L'], OUT => 'L'},
|
295
|
+
'WaitForInputIdle' => {DLL => 'kernel32', NAME => 'WaitForInputIdle',
|
296
|
+
IN => ['L', 'L'], OUT => 'L'}
|
297
|
+
)
|
298
|
+
|
299
|
+
#-----------------------------------------------------------------------------------------
|
300
|
+
# constsFor: "Process Creation Flags"
|
301
|
+
# (from WinBase.h)
|
302
|
+
DEBUG_PROCESS = 0x00000001
|
303
|
+
DEBUG_ONLY_THIS_PROCESS = 0x00000002
|
304
|
+
CREATE_SUSPENDED = 0x00000004
|
305
|
+
DETACHED_PROCESS = 0x00000008
|
306
|
+
CREATE_NEW_CONSOLE = 0x00000010
|
307
|
+
NORMAL_PRIORITY_CLASS = 0x00000020
|
308
|
+
IDLE_PRIORITY_CLASS = 0x00000040
|
309
|
+
HIGH_PRIORITY_CLASS = 0x00000080
|
310
|
+
REALTIME_PRIORITY_CLASS = 0x00000100
|
311
|
+
CREATE_NEW_PROCESS_GROUP = 0x00000200
|
312
|
+
CREATE_UNICODE_ENVIRONMENT = 0x00000400
|
313
|
+
CREATE_SEPARATE_WOW_VDM = 0x00000800
|
314
|
+
CREATE_SHARED_WOW_VDM = 0x00001000
|
315
|
+
CREATE_FORCED_DOS = 0x00002000
|
316
|
+
CREATE_DEFAULT_ERROR_MODE = 0x04000000
|
317
|
+
CREATE_NO_WINDOW = 0x08000000
|
318
|
+
PROFILE_USER = 0x10000000
|
319
|
+
PROFILE_KERNEL = 0x20000000
|
320
|
+
PROFILE_SERVER = 0x40000000
|
321
|
+
|
322
|
+
#-----------------------------------------------------------------------------------------
|
323
|
+
# constsFor: "Thread Creation Flags"
|
324
|
+
# (from WinBase.h, WinNT.h)
|
325
|
+
THREAD_BASE_PRIORITY_LOWRT = 15
|
326
|
+
THREAD_BASE_PRIORITY_MAX = 2
|
327
|
+
THREAD_BASE_PRIORITY_MIN = -2
|
328
|
+
THREAD_BASE_PRIORITY_IDLE = -15
|
329
|
+
MAXLONG = 0x7FFFFFFFFFFFFFFF
|
330
|
+
THREAD_PRIORITY_LOWEST = THREAD_BASE_PRIORITY_MIN
|
331
|
+
THREAD_PRIORITY_BELOW_NORMAL = THREAD_PRIORITY_LOWEST + 1
|
332
|
+
THREAD_PRIORITY_NORMAL = 0
|
333
|
+
THREAD_PRIORITY_HIGHEST = THREAD_BASE_PRIORITY_MAX
|
334
|
+
THREAD_PRIORITY_ABOVE_NORMAL = THREAD_PRIORITY_HIGHEST - 1
|
335
|
+
THREAD_PRIORITY_ERROR_RETURN = MAXLONG
|
336
|
+
THREAD_PRIORITY_TIME_CRITICAL = THREAD_BASE_PRIORITY_LOWRT
|
337
|
+
THREAD_PRIORITY_IDLE = THREAD_BASE_PRIORITY_IDLE
|
338
|
+
|
339
|
+
attr_reader :proc
|
340
|
+
#-----------------------------------------------------------------------------------------
|
341
|
+
# class methodsFor: "initialization"
|
342
|
+
def initialize()
|
343
|
+
@proc = nil
|
344
|
+
end
|
345
|
+
|
346
|
+
#-----------------------------------------------------------------------------------------
|
347
|
+
# methodsFor: "process creation"
|
348
|
+
def Process.create(
|
349
|
+
p_strAppName,
|
350
|
+
p_strCmdLine,
|
351
|
+
p_processAttrs = nil,
|
352
|
+
p_threadAttrs = nil,
|
353
|
+
p_bInheritHandles = false,
|
354
|
+
p_nCreationFlags = NORMAL_PRIORITY_CLASS,
|
355
|
+
p_strEnvironment = nil,
|
356
|
+
p_strCurrentDirectory = nil,
|
357
|
+
p_startupInfo = nil)
|
358
|
+
process = Process.new()
|
359
|
+
process.create(
|
360
|
+
p_strAppName, p_strCmdLine,
|
361
|
+
p_processAttrs, p_threadAttrs, p_bInheritHandles,
|
362
|
+
p_nCreationFlags, p_strEnvironment, p_strCurrentDirectory, p_startupInfo)
|
363
|
+
return process
|
364
|
+
end
|
365
|
+
|
366
|
+
def create(
|
367
|
+
p_strAppName,
|
368
|
+
p_strCmdLine,
|
369
|
+
p_processAttrs = nil,
|
370
|
+
p_threadAttrs = nil,
|
371
|
+
p_bInheritHandles = false,
|
372
|
+
p_nCreationFlags = NORMAL_PRIORITY_CLASS,
|
373
|
+
p_strEnvironment = nil,
|
374
|
+
p_strCurrentDirectory = nil,
|
375
|
+
p_startupInfo = nil)
|
376
|
+
self.close() if !@proc.nil?
|
377
|
+
pProcessInfo = " " * ProcessInfo.sizeof
|
378
|
+
ret = WCall('CreateProcess',
|
379
|
+
p_strAppName, p_strCmdLine,
|
380
|
+
p_processAttrs, p_threadAttrs, p_bInheritHandles ? 1 : 0,
|
381
|
+
p_nCreationFlags, p_strEnvironment, p_strCurrentDirectory,
|
382
|
+
p_startupInfo.nil? ? StartupInfo.new().pack : p_startupInfo.pack,
|
383
|
+
pProcessInfo)
|
384
|
+
$TRACE.debug 9, "after CreateProcess ret = #{ret.inspect}"
|
385
|
+
@proc = ProcessInfo.unpack(pProcessInfo)
|
386
|
+
|
387
|
+
if ret == 0 then
|
388
|
+
raise Win32::Error.new("process '#{p_strAppName}' could not be created because, ")
|
389
|
+
elsif @proc.pid == 0
|
390
|
+
raise Win32::Error.new, "process '#{p_strAppName}' could not be created (unknown reason)", caller
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
def Process.open(p_processAttrs, p_bInheritHandles, p_pid)
|
395
|
+
process = Process.new()
|
396
|
+
process.open(p_processAttrs, p_bInheritHandles, p_pid)
|
397
|
+
end
|
398
|
+
|
399
|
+
def open(p_processAttrs, p_bInheritHandles, p_pid)
|
400
|
+
self.close() if !@proc.nil?
|
401
|
+
ret = WCall('CreateProcess', p_processAttrs, p_bInheritHandles, p_pid)
|
402
|
+
raise Win32::Error.new, "Cannot Open Process", caller if 0 == ret
|
403
|
+
@proc = ProcessInfo.new(ret)
|
404
|
+
end
|
405
|
+
|
406
|
+
#-----------------------------------------------------------------------------------------
|
407
|
+
# methodsFor: "closing"
|
408
|
+
def close
|
409
|
+
return 0 if @proc.nil?
|
410
|
+
end
|
411
|
+
|
412
|
+
#-----------------------------------------------------------------------------------------
|
413
|
+
# methodsFor: "terminating"
|
414
|
+
def terminate(p_nExitCode)
|
415
|
+
raise Win32::Error.new, "Missing Process Info", caller if @proc.nil?
|
416
|
+
ret = WCall('TerminateProcess', @proc.hProcess, p_nExitCode)
|
417
|
+
raise Win32::Error.new, "Error terminating process #{@proc.hProcess}", caller if 0 == ret
|
418
|
+
end
|
419
|
+
|
420
|
+
#-----------------------------------------------------------------------------------------
|
421
|
+
# methodsFor: "signalling"
|
422
|
+
def wait(p_nMilliseconds, p_bAlertable = true)
|
423
|
+
raise Win32::Error.new, "Missing Process Info", caller if @proc.nil?
|
424
|
+
ret = WCall('WaitForObject', @proc.hProcess, p_nMilliseconds, p_bAlertable ? 1 : 0)
|
425
|
+
raise Win32::Error.new, "Error while waiting for #{@proc.pid}", caller if ret == WAIT_FAILED
|
426
|
+
return ret
|
427
|
+
end
|
428
|
+
|
429
|
+
def waitForInputIdle(p_nMilliseconds)
|
430
|
+
raise Win32::Error.new, "Missing Process Info", caller if @proc.nil?
|
431
|
+
ret = WCall('WaitForInputIdle', @proc.hProcess, p_nMilliseconds)
|
432
|
+
raise Win32::Error.new, "Error while waiting for #{@proc.pid}", caller if ret == WAIT_FAILED
|
433
|
+
return ret
|
434
|
+
end
|
435
|
+
|
436
|
+
def close_handles
|
437
|
+
if !@proc.nil? then
|
438
|
+
closeHandle = Win32API.new("kernel32", "CloseHandle", ['L'], 'L')
|
439
|
+
closeHandle.Call(@proc.hProcess) if @proc.hProcess != nil
|
440
|
+
closeHandle.Call(@proc.hThread) if @proc.hThread != nil
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
444
|
+
#-----------------------------------------------------------------------------------------
|
445
|
+
# methodsFor: "accessing"
|
446
|
+
def hProcess
|
447
|
+
return @proc.nil? ? nil : @proc.hProcess
|
448
|
+
end
|
449
|
+
|
450
|
+
def hThread
|
451
|
+
return @proc.nil? ? nil : @proc.hThread
|
452
|
+
end
|
453
|
+
|
454
|
+
def pid
|
455
|
+
return @proc.nil? ? nil : @proc.pid
|
456
|
+
end
|
457
|
+
|
458
|
+
def tid
|
459
|
+
return @proc.nil? ? nil : @proc.tid
|
460
|
+
end
|
461
|
+
|
462
|
+
#-----------------------------------------------------------------------------------------
|
463
|
+
# methodsFor: "printing"
|
464
|
+
def to_s
|
465
|
+
return @proc.nil? ? "nil" : @proc.to_s
|
466
|
+
end
|
467
|
+
end
|
468
|
+
end
|