~ubuntu-branches/ubuntu/quantal/enigmail/quantal-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: 2013-09-13 16:02:15 UTC
  • mfrom: (0.12.16)
  • Revision ID: package-import@ubuntu.com-20130913160215-u3g8nmwa0pdwagwc
Tags: 2:1.5.2-0ubuntu0.12.10.1
* New upstream release v1.5.2 for Thunderbird 24

* Build enigmail using a stripped down Thunderbird 17 build system, as it's
  now quite difficult to build the way we were doing previously, with the
  latest Firefox build system
* Add debian/patches/no_libxpcom.patch - Don't link against libxpcom, as it
  doesn't exist anymore (but exists in the build system)
* Add debian/patches/use_sdk.patch - Use the SDK version of xpt.py and
  friends
* Drop debian/patches/ipc-pipe_rename.diff (not needed anymore)
* Drop debian/patches/makefile_depth.diff (not needed anymore)

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()