vrvirtualdesktop 0.0.1
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 +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
|