~ubuntu-branches/ubuntu/precise/enigmail/precise-security

« back to all changes in this revision

Viewing changes to testing/mozbase/mozprocess/mozprocess/winprocess.py

  • Committer: Package Import Robot
  • Author(s): Chris Coulson
  • Date: 2012-11-12 16:36:01 UTC
  • mfrom: (0.12.15)
  • Revision ID: package-import@ubuntu.com-20121112163601-t8e8skdfi3ni9iqp
Tags: 2:1.4.6-0ubuntu0.12.04.1
* New upstream release v1.4.6
  - see LP: #1080212 for USN information
* Drop unneeded patches
  - remove debian/patches/correct-version-number.diff
  - remove debian/patches/dont_register_cids_multiple_times.diff
  - update debian/patches/series
* Support building in an objdir
  - update debian/rules

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# A module to expose various thread/process/job related structures and
 
2
# methods from kernel32
 
3
#
 
4
# The MIT License
 
5
#
 
6
# Copyright (c) 2003-2004 by Peter Astrand <astrand@lysator.liu.se>
 
7
#
 
8
# Additions and modifications written by Benjamin Smedberg
 
9
# <benjamin@smedbergs.us> are Copyright (c) 2006 by the Mozilla Foundation
 
10
# <http://www.mozilla.org/>
 
11
#
 
12
# More Modifications
 
13
# Copyright (c) 2006-2007 by Mike Taylor <bear@code-bear.com>
 
14
# Copyright (c) 2007-2008 by Mikeal Rogers <mikeal@mozilla.com>
 
15
#
 
16
# By obtaining, using, and/or copying this software and/or its
 
17
# associated documentation, you agree that you have read, understood,
 
18
# and will comply with the following terms and conditions:
 
19
#
 
20
# Permission to use, copy, modify, and distribute this software and
 
21
# its associated documentation for any purpose and without fee is
 
22
# hereby granted, provided that the above copyright notice appears in
 
23
# all copies, and that both that copyright notice and this permission
 
24
# notice appear in supporting documentation, and that the name of the
 
25
# author not be used in advertising or publicity pertaining to
 
26
# distribution of the software without specific, written prior
 
27
# permission.
 
28
#
 
29
# THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 
30
# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
 
31
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 
32
# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
 
33
# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 
34
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 
35
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
36
 
 
37
from ctypes import c_void_p, POINTER, sizeof, Structure, Union, windll, WinError, WINFUNCTYPE, c_ulong
 
38
from ctypes.wintypes import BOOL, BYTE, DWORD, HANDLE, LPCWSTR, LPWSTR, UINT, WORD, ULONG
 
39
from qijo import QueryInformationJobObject
 
40
 
 
41
LPVOID = c_void_p
 
42
LPBYTE = POINTER(BYTE)
 
43
LPDWORD = POINTER(DWORD)
 
44
LPBOOL = POINTER(BOOL)
 
45
LPULONG = POINTER(c_ulong)
 
46
 
 
47
def ErrCheckBool(result, func, args):
 
48
    """errcheck function for Windows functions that return a BOOL True
 
49
    on success"""
 
50
    if not result:
 
51
        raise WinError()
 
52
    return args
 
53
 
 
54
 
 
55
# AutoHANDLE
 
56
 
 
57
class AutoHANDLE(HANDLE):
 
58
    """Subclass of HANDLE which will call CloseHandle() on deletion."""
 
59
    
 
60
    CloseHandleProto = WINFUNCTYPE(BOOL, HANDLE)
 
61
    CloseHandle = CloseHandleProto(("CloseHandle", windll.kernel32))
 
62
    CloseHandle.errcheck = ErrCheckBool
 
63
    
 
64
    def Close(self):
 
65
        if self.value and self.value != HANDLE(-1).value:
 
66
            self.CloseHandle(self)
 
67
            self.value = 0
 
68
    
 
69
    def __del__(self):
 
70
        self.Close()
 
71
 
 
72
    def __int__(self):
 
73
        return self.value
 
74
 
 
75
def ErrCheckHandle(result, func, args):
 
76
    """errcheck function for Windows functions that return a HANDLE."""
 
77
    if not result:
 
78
        raise WinError()
 
79
    return AutoHANDLE(result)
 
80
 
 
81
# PROCESS_INFORMATION structure
 
82
 
 
83
class PROCESS_INFORMATION(Structure):
 
84
    _fields_ = [("hProcess", HANDLE),
 
85
                ("hThread", HANDLE),
 
86
                ("dwProcessID", DWORD),
 
87
                ("dwThreadID", DWORD)]
 
88
 
 
89
    def __init__(self):
 
90
        Structure.__init__(self)
 
91
        
 
92
        self.cb = sizeof(self)
 
93
 
 
94
LPPROCESS_INFORMATION = POINTER(PROCESS_INFORMATION)
 
95
 
 
96
# STARTUPINFO structure
 
97
 
 
98
class STARTUPINFO(Structure):
 
99
    _fields_ = [("cb", DWORD),
 
100
                ("lpReserved", LPWSTR),
 
101
                ("lpDesktop", LPWSTR),
 
102
                ("lpTitle", LPWSTR),
 
103
                ("dwX", DWORD),
 
104
                ("dwY", DWORD),
 
105
                ("dwXSize", DWORD),
 
106
                ("dwYSize", DWORD),
 
107
                ("dwXCountChars", DWORD),
 
108
                ("dwYCountChars", DWORD),
 
109
                ("dwFillAttribute", DWORD),
 
110
                ("dwFlags", DWORD),
 
111
                ("wShowWindow", WORD),
 
112
                ("cbReserved2", WORD),
 
113
                ("lpReserved2", LPBYTE),
 
114
                ("hStdInput", HANDLE),
 
115
                ("hStdOutput", HANDLE),
 
116
                ("hStdError", HANDLE)
 
117
                ]
 
118
LPSTARTUPINFO = POINTER(STARTUPINFO)
 
119
 
 
120
SW_HIDE                 = 0
 
121
 
 
122
STARTF_USESHOWWINDOW    = 0x01
 
123
STARTF_USESIZE          = 0x02
 
124
STARTF_USEPOSITION      = 0x04
 
125
STARTF_USECOUNTCHARS    = 0x08
 
126
STARTF_USEFILLATTRIBUTE = 0x10
 
127
STARTF_RUNFULLSCREEN    = 0x20
 
128
STARTF_FORCEONFEEDBACK  = 0x40
 
129
STARTF_FORCEOFFFEEDBACK = 0x80
 
130
STARTF_USESTDHANDLES    = 0x100
 
131
 
 
132
# EnvironmentBlock
 
133
 
 
134
class EnvironmentBlock:
 
135
    """An object which can be passed as the lpEnv parameter of CreateProcess.
 
136
    It is initialized with a dictionary."""
 
137
 
 
138
    def __init__(self, dict):
 
139
        if not dict:
 
140
            self._as_parameter_ = None
 
141
        else:
 
142
            values = ["%s=%s" % (key, value)
 
143
                      for (key, value) in dict.iteritems()]
 
144
            values.append("")
 
145
            self._as_parameter_ = LPCWSTR("\0".join(values))
 
146
 
 
147
# Error Messages we need to watch for go here
 
148
# See: http://msdn.microsoft.com/en-us/library/ms681388%28v=vs.85%29.aspx
 
149
ERROR_ABANDONED_WAIT_0 = 735
 
150
            
 
151
# GetLastError()
 
152
GetLastErrorProto = WINFUNCTYPE(DWORD                   # Return Type
 
153
                               )
 
154
GetLastErrorFlags = ()
 
155
GetLastError = GetLastErrorProto(("GetLastError", windll.kernel32), GetLastErrorFlags)
 
156
 
 
157
# CreateProcess()
 
158
 
 
159
CreateProcessProto = WINFUNCTYPE(BOOL,                  # Return type
 
160
                                 LPCWSTR,               # lpApplicationName
 
161
                                 LPWSTR,                # lpCommandLine
 
162
                                 LPVOID,                # lpProcessAttributes
 
163
                                 LPVOID,                # lpThreadAttributes
 
164
                                 BOOL,                  # bInheritHandles
 
165
                                 DWORD,                 # dwCreationFlags
 
166
                                 LPVOID,                # lpEnvironment
 
167
                                 LPCWSTR,               # lpCurrentDirectory
 
168
                                 LPSTARTUPINFO,         # lpStartupInfo
 
169
                                 LPPROCESS_INFORMATION  # lpProcessInformation
 
170
                                 )
 
171
 
 
172
CreateProcessFlags = ((1, "lpApplicationName", None),
 
173
                      (1, "lpCommandLine"),
 
174
                      (1, "lpProcessAttributes", None),
 
175
                      (1, "lpThreadAttributes", None),
 
176
                      (1, "bInheritHandles", True),
 
177
                      (1, "dwCreationFlags", 0),
 
178
                      (1, "lpEnvironment", None),
 
179
                      (1, "lpCurrentDirectory", None),
 
180
                      (1, "lpStartupInfo"),
 
181
                      (2, "lpProcessInformation"))
 
182
 
 
183
def ErrCheckCreateProcess(result, func, args):
 
184
    ErrCheckBool(result, func, args)
 
185
    # return a tuple (hProcess, hThread, dwProcessID, dwThreadID)
 
186
    pi = args[9]
 
187
    return AutoHANDLE(pi.hProcess), AutoHANDLE(pi.hThread), pi.dwProcessID, pi.dwThreadID
 
188
 
 
189
CreateProcess = CreateProcessProto(("CreateProcessW", windll.kernel32),
 
190
                                   CreateProcessFlags)
 
191
CreateProcess.errcheck = ErrCheckCreateProcess
 
192
 
 
193
# flags for CreateProcess
 
194
CREATE_BREAKAWAY_FROM_JOB = 0x01000000
 
195
CREATE_DEFAULT_ERROR_MODE = 0x04000000
 
196
CREATE_NEW_CONSOLE = 0x00000010
 
197
CREATE_NEW_PROCESS_GROUP = 0x00000200
 
198
CREATE_NO_WINDOW = 0x08000000
 
199
CREATE_SUSPENDED = 0x00000004
 
200
CREATE_UNICODE_ENVIRONMENT = 0x00000400
 
201
 
 
202
# Flags for IOCompletion ports (some of these would probably be defined if 
 
203
# we used the win32 extensions for python, but we don't want to do that if we 
 
204
# can help it.
 
205
INVALID_HANDLE_VALUE = HANDLE(-1) # From winbase.h
 
206
 
 
207
# Self Defined Constants for IOPort <--> Job Object communication
 
208
COMPKEY_TERMINATE = c_ulong(0)
 
209
COMPKEY_JOBOBJECT = c_ulong(1)
 
210
 
 
211
# flags for job limit information
 
212
# see http://msdn.microsoft.com/en-us/library/ms684147%28VS.85%29.aspx
 
213
JOB_OBJECT_LIMIT_BREAKAWAY_OK = 0x00000800
 
214
JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK = 0x00001000
 
215
 
 
216
# Flags for Job Object Completion Port Message IDs from winnt.h
 
217
# See also: http://msdn.microsoft.com/en-us/library/ms684141%28v=vs.85%29.aspx
 
218
JOB_OBJECT_MSG_END_OF_JOB_TIME =          1
 
219
JOB_OBJECT_MSG_END_OF_PROCESS_TIME =      2
 
220
JOB_OBJECT_MSG_ACTIVE_PROCESS_LIMIT =     3
 
221
JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO =      4
 
222
JOB_OBJECT_MSG_NEW_PROCESS =              6
 
223
JOB_OBJECT_MSG_EXIT_PROCESS =             7
 
224
JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS =    8
 
225
JOB_OBJECT_MSG_PROCESS_MEMORY_LIMIT =     9
 
226
JOB_OBJECT_MSG_JOB_MEMORY_LIMIT =         10
 
227
 
 
228
# See winbase.h
 
229
DEBUG_ONLY_THIS_PROCESS = 0x00000002
 
230
DEBUG_PROCESS = 0x00000001
 
231
DETACHED_PROCESS = 0x00000008
 
232
    
 
233
# GetQueuedCompletionPortStatus - http://msdn.microsoft.com/en-us/library/aa364986%28v=vs.85%29.aspx
 
234
GetQueuedCompletionStatusProto = WINFUNCTYPE(BOOL,         # Return Type
 
235
                                             HANDLE,       # Completion Port
 
236
                                             LPDWORD,      # Msg ID
 
237
                                             LPULONG,      # Completion Key
 
238
                                             LPULONG,      # PID Returned from the call (may be null)
 
239
                                             DWORD)        # milliseconds to wait
 
240
GetQueuedCompletionStatusFlags = ((1, "CompletionPort", INVALID_HANDLE_VALUE),
 
241
                                  (1, "lpNumberOfBytes", None),
 
242
                                  (1, "lpCompletionKey", None),
 
243
                                  (1, "lpPID", None),
 
244
                                  (1, "dwMilliseconds", 0))
 
245
GetQueuedCompletionStatus = GetQueuedCompletionStatusProto(("GetQueuedCompletionStatus",
 
246
                                                            windll.kernel32),
 
247
                                                           GetQueuedCompletionStatusFlags)
 
248
 
 
249
# CreateIOCompletionPort
 
250
# Note that the completion key is just a number, not a pointer.
 
251
CreateIoCompletionPortProto = WINFUNCTYPE(HANDLE,      # Return Type
 
252
                                          HANDLE,      # File Handle
 
253
                                          HANDLE,      # Existing Completion Port
 
254
                                          c_ulong,     # Completion Key
 
255
                                          DWORD        # Number of Threads
 
256
                                         )
 
257
CreateIoCompletionPortFlags = ((1, "FileHandle", INVALID_HANDLE_VALUE),
 
258
                               (1, "ExistingCompletionPort", 0),
 
259
                               (1, "CompletionKey", c_ulong(0)),
 
260
                               (1, "NumberOfConcurrentThreads", 0))
 
261
CreateIoCompletionPort = CreateIoCompletionPortProto(("CreateIoCompletionPort",
 
262
                                                      windll.kernel32),
 
263
                                                      CreateIoCompletionPortFlags)
 
264
CreateIoCompletionPort.errcheck = ErrCheckHandle
 
265
 
 
266
# SetInformationJobObject
 
267
SetInformationJobObjectProto = WINFUNCTYPE(BOOL,      # Return Type
 
268
                                           HANDLE,    # Job Handle
 
269
                                           DWORD,     # Type of Class next param is
 
270
                                           LPVOID,    # Job Object Class
 
271
                                           DWORD      # Job Object Class Length
 
272
                                          )
 
273
SetInformationJobObjectProtoFlags = ((1, "hJob", None),
 
274
                                     (1, "JobObjectInfoClass", None),
 
275
                                     (1, "lpJobObjectInfo", None),
 
276
                                     (1, "cbJobObjectInfoLength", 0))
 
277
SetInformationJobObject = SetInformationJobObjectProto(("SetInformationJobObject",
 
278
                                                        windll.kernel32),
 
279
                                                        SetInformationJobObjectProtoFlags)
 
280
SetInformationJobObject.errcheck = ErrCheckBool
 
281
 
 
282
# CreateJobObject()
 
283
CreateJobObjectProto = WINFUNCTYPE(HANDLE,             # Return type
 
284
                                   LPVOID,             # lpJobAttributes
 
285
                                   LPCWSTR             # lpName
 
286
                                   )
 
287
 
 
288
CreateJobObjectFlags = ((1, "lpJobAttributes", None),
 
289
                        (1, "lpName", None))
 
290
 
 
291
CreateJobObject = CreateJobObjectProto(("CreateJobObjectW", windll.kernel32),
 
292
                                       CreateJobObjectFlags)
 
293
CreateJobObject.errcheck = ErrCheckHandle
 
294
 
 
295
# AssignProcessToJobObject()
 
296
 
 
297
AssignProcessToJobObjectProto = WINFUNCTYPE(BOOL,      # Return type
 
298
                                            HANDLE,    # hJob
 
299
                                            HANDLE     # hProcess
 
300
                                            )
 
301
AssignProcessToJobObjectFlags = ((1, "hJob"),
 
302
                                 (1, "hProcess"))
 
303
AssignProcessToJobObject = AssignProcessToJobObjectProto(
 
304
    ("AssignProcessToJobObject", windll.kernel32),
 
305
    AssignProcessToJobObjectFlags)
 
306
AssignProcessToJobObject.errcheck = ErrCheckBool
 
307
 
 
308
# GetCurrentProcess()
 
309
# because os.getPid() is way too easy
 
310
GetCurrentProcessProto = WINFUNCTYPE(HANDLE    # Return type
 
311
                                     )
 
312
GetCurrentProcessFlags = ()
 
313
GetCurrentProcess = GetCurrentProcessProto(
 
314
    ("GetCurrentProcess", windll.kernel32),
 
315
    GetCurrentProcessFlags)
 
316
GetCurrentProcess.errcheck = ErrCheckHandle
 
317
 
 
318
# IsProcessInJob()
 
319
try:
 
320
    IsProcessInJobProto = WINFUNCTYPE(BOOL,     # Return type
 
321
                                      HANDLE,   # Process Handle
 
322
                                      HANDLE,   # Job Handle
 
323
                                      LPBOOL      # Result
 
324
                                      )
 
325
    IsProcessInJobFlags = ((1, "ProcessHandle"),
 
326
                           (1, "JobHandle", HANDLE(0)),
 
327
                           (2, "Result"))
 
328
    IsProcessInJob = IsProcessInJobProto(
 
329
        ("IsProcessInJob", windll.kernel32),
 
330
        IsProcessInJobFlags)
 
331
    IsProcessInJob.errcheck = ErrCheckBool 
 
332
except AttributeError:
 
333
    # windows 2k doesn't have this API
 
334
    def IsProcessInJob(process):
 
335
        return False
 
336
 
 
337
 
 
338
# ResumeThread()
 
339
 
 
340
def ErrCheckResumeThread(result, func, args):
 
341
    if result == -1:
 
342
        raise WinError()
 
343
 
 
344
    return args
 
345
 
 
346
ResumeThreadProto = WINFUNCTYPE(DWORD,      # Return type
 
347
                                HANDLE      # hThread
 
348
                                )
 
349
ResumeThreadFlags = ((1, "hThread"),)
 
350
ResumeThread = ResumeThreadProto(("ResumeThread", windll.kernel32),
 
351
                                 ResumeThreadFlags)
 
352
ResumeThread.errcheck = ErrCheckResumeThread
 
353
 
 
354
# TerminateProcess()
 
355
 
 
356
TerminateProcessProto = WINFUNCTYPE(BOOL,   # Return type
 
357
                                    HANDLE, # hProcess
 
358
                                    UINT    # uExitCode
 
359
                                    )
 
360
TerminateProcessFlags = ((1, "hProcess"),
 
361
                         (1, "uExitCode", 127))
 
362
TerminateProcess = TerminateProcessProto(
 
363
    ("TerminateProcess", windll.kernel32),
 
364
    TerminateProcessFlags)
 
365
TerminateProcess.errcheck = ErrCheckBool
 
366
 
 
367
# TerminateJobObject()
 
368
 
 
369
TerminateJobObjectProto = WINFUNCTYPE(BOOL,   # Return type
 
370
                                      HANDLE, # hJob
 
371
                                      UINT    # uExitCode
 
372
                                      )
 
373
TerminateJobObjectFlags = ((1, "hJob"),
 
374
                           (1, "uExitCode", 127))
 
375
TerminateJobObject = TerminateJobObjectProto(
 
376
    ("TerminateJobObject", windll.kernel32),
 
377
    TerminateJobObjectFlags)
 
378
TerminateJobObject.errcheck = ErrCheckBool
 
379
 
 
380
# WaitForSingleObject()
 
381
 
 
382
WaitForSingleObjectProto = WINFUNCTYPE(DWORD,  # Return type
 
383
                                       HANDLE, # hHandle
 
384
                                       DWORD,  # dwMilliseconds
 
385
                                       )
 
386
WaitForSingleObjectFlags = ((1, "hHandle"),
 
387
                            (1, "dwMilliseconds", -1))
 
388
WaitForSingleObject = WaitForSingleObjectProto(
 
389
    ("WaitForSingleObject", windll.kernel32),
 
390
    WaitForSingleObjectFlags)
 
391
 
 
392
# http://msdn.microsoft.com/en-us/library/ms681381%28v=vs.85%29.aspx
 
393
INFINITE = -1
 
394
WAIT_TIMEOUT = 0x0102
 
395
WAIT_OBJECT_0 = 0x0
 
396
WAIT_ABANDONED = 0x0080
 
397
 
 
398
# http://msdn.microsoft.com/en-us/library/ms683189%28VS.85%29.aspx
 
399
STILL_ACTIVE = 259
 
400
 
 
401
# Used when we terminate a process.
 
402
ERROR_CONTROL_C_EXIT = 0x23c
 
403
 
 
404
# GetExitCodeProcess()
 
405
 
 
406
GetExitCodeProcessProto = WINFUNCTYPE(BOOL,    # Return type
 
407
                                      HANDLE,  # hProcess
 
408
                                      LPDWORD, # lpExitCode
 
409
                                      )
 
410
GetExitCodeProcessFlags = ((1, "hProcess"),
 
411
                           (2, "lpExitCode"))
 
412
GetExitCodeProcess = GetExitCodeProcessProto(
 
413
    ("GetExitCodeProcess", windll.kernel32),
 
414
    GetExitCodeProcessFlags)
 
415
GetExitCodeProcess.errcheck = ErrCheckBool
 
416
 
 
417
def CanCreateJobObject():
 
418
    currentProc = GetCurrentProcess()
 
419
    if IsProcessInJob(currentProc):
 
420
        jobinfo = QueryInformationJobObject(HANDLE(0), 'JobObjectExtendedLimitInformation')
 
421
        limitflags = jobinfo['BasicLimitInformation']['LimitFlags']
 
422
        return bool(limitflags & JOB_OBJECT_LIMIT_BREAKAWAY_OK) or bool(limitflags & JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK)
 
423
    else:
 
424
        return True
 
425
 
 
426
### testing functions
 
427
 
 
428
def parent():
 
429
    print 'Starting parent'
 
430
    currentProc = GetCurrentProcess()
 
431
    if IsProcessInJob(currentProc):
 
432
        print >> sys.stderr, "You should not be in a job object to test"
 
433
        sys.exit(1)
 
434
    assert CanCreateJobObject()
 
435
    print 'File: %s' % __file__
 
436
    command = [sys.executable, __file__, '-child']
 
437
    print 'Running command: %s' % command
 
438
    process = Popen(command)
 
439
    process.kill()
 
440
    code = process.returncode
 
441
    print 'Child code: %s' % code
 
442
    assert code == 127
 
443
        
 
444
def child():
 
445
    print 'Starting child'
 
446
    currentProc = GetCurrentProcess()
 
447
    injob = IsProcessInJob(currentProc)
 
448
    print "Is in a job?: %s" % injob
 
449
    can_create = CanCreateJobObject()
 
450
    print 'Can create job?: %s' % can_create
 
451
    process = Popen('c:\\windows\\notepad.exe')
 
452
    assert process._job
 
453
    jobinfo = QueryInformationJobObject(process._job, 'JobObjectExtendedLimitInformation')
 
454
    print 'Job info: %s' % jobinfo
 
455
    limitflags = jobinfo['BasicLimitInformation']['LimitFlags']
 
456
    print 'LimitFlags: %s' % limitflags
 
457
    process.kill()