Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
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.
37 from ctypes import c_void_p, POINTER, sizeof, Structure, windll, WinError, WINFUNCTYPE
38 from ctypes.wintypes import BOOL, BYTE, DWORD, HANDLE, LPCWSTR, LPWSTR, UINT, WORD, \
39 c_buffer, c_ulong, byref
40 from qijo import QueryInformationJobObject
42 LPVOID = c_void_p
43 LPBYTE = POINTER(BYTE)
44 LPDWORD = POINTER(DWORD)
45 LPBOOL = POINTER(BOOL)
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
55 # AutoHANDLE
57 class AutoHANDLE(HANDLE):
58 """Subclass of HANDLE which will call CloseHandle() on deletion."""
60 CloseHandleProto = WINFUNCTYPE(BOOL, HANDLE)
61 CloseHandle = CloseHandleProto(("CloseHandle", windll.kernel32))
62 CloseHandle.errcheck = ErrCheckBool
64 def Close(self):
65 if self.value and self.value != HANDLE(-1).value:
66 self.CloseHandle(self)
67 self.value = 0
69 def __del__(self):
70 self.Close()
72 def __int__(self):
73 return self.value
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)
81 # PROCESS_INFORMATION structure
83 class PROCESS_INFORMATION(Structure):
84 _fields_ = [("hProcess", HANDLE),
85 ("hThread", HANDLE),
86 ("dwProcessID", DWORD),
87 ("dwThreadID", DWORD)]
89 def __init__(self):
90 Structure.__init__(self)
92 self.cb = sizeof(self)
94 LPPROCESS_INFORMATION = POINTER(PROCESS_INFORMATION)
96 # STARTUPINFO structure
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)
120 SW_HIDE = 0
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
132 # EnvironmentBlock
134 class EnvironmentBlock:
135 """An object which can be passed as the lpEnv parameter of CreateProcess.
136 It is initialized with a dictionary."""
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))
147 # CreateProcess()
149 CreateProcessProto = WINFUNCTYPE(BOOL, # Return type
150 LPCWSTR, # lpApplicationName
151 LPWSTR, # lpCommandLine
152 LPVOID, # lpProcessAttributes
153 LPVOID, # lpThreadAttributes
154 BOOL, # bInheritHandles
155 DWORD, # dwCreationFlags
156 LPVOID, # lpEnvironment
157 LPCWSTR, # lpCurrentDirectory
158 LPSTARTUPINFO, # lpStartupInfo
159 LPPROCESS_INFORMATION # lpProcessInformation
160 )
162 CreateProcessFlags = ((1, "lpApplicationName", None),
163 (1, "lpCommandLine"),
164 (1, "lpProcessAttributes", None),
165 (1, "lpThreadAttributes", None),
166 (1, "bInheritHandles", True),
167 (1, "dwCreationFlags", 0),
168 (1, "lpEnvironment", None),
169 (1, "lpCurrentDirectory", None),
170 (1, "lpStartupInfo"),
171 (2, "lpProcessInformation"))
173 def ErrCheckCreateProcess(result, func, args):
174 ErrCheckBool(result, func, args)
175 # return a tuple (hProcess, hThread, dwProcessID, dwThreadID)
176 pi = args[9]
177 return AutoHANDLE(pi.hProcess), AutoHANDLE(pi.hThread), pi.dwProcessID, pi.dwThreadID
179 CreateProcess = CreateProcessProto(("CreateProcessW", windll.kernel32),
180 CreateProcessFlags)
181 CreateProcess.errcheck = ErrCheckCreateProcess
183 # flags for CreateProcess
184 CREATE_BREAKAWAY_FROM_JOB = 0x01000000
185 CREATE_DEFAULT_ERROR_MODE = 0x04000000
186 CREATE_NEW_CONSOLE = 0x00000010
187 CREATE_NEW_PROCESS_GROUP = 0x00000200
188 CREATE_NO_WINDOW = 0x08000000
189 CREATE_SUSPENDED = 0x00000004
190 CREATE_UNICODE_ENVIRONMENT = 0x00000400
192 # flags for job limit information
193 # see http://msdn.microsoft.com/en-us/library/ms684147%28VS.85%29.aspx
194 JOB_OBJECT_LIMIT_BREAKAWAY_OK = 0x00000800
195 JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK = 0x00001000
197 # XXX these flags should be documented
198 DEBUG_ONLY_THIS_PROCESS = 0x00000002
199 DEBUG_PROCESS = 0x00000001
200 DETACHED_PROCESS = 0x00000008
202 # CreateJobObject()
204 CreateJobObjectProto = WINFUNCTYPE(HANDLE, # Return type
205 LPVOID, # lpJobAttributes
206 LPCWSTR # lpName
207 )
209 CreateJobObjectFlags = ((1, "lpJobAttributes", None),
210 (1, "lpName", None))
212 CreateJobObject = CreateJobObjectProto(("CreateJobObjectW", windll.kernel32),
213 CreateJobObjectFlags)
214 CreateJobObject.errcheck = ErrCheckHandle
216 # AssignProcessToJobObject()
218 AssignProcessToJobObjectProto = WINFUNCTYPE(BOOL, # Return type
219 HANDLE, # hJob
220 HANDLE # hProcess
221 )
222 AssignProcessToJobObjectFlags = ((1, "hJob"),
223 (1, "hProcess"))
224 AssignProcessToJobObject = AssignProcessToJobObjectProto(
225 ("AssignProcessToJobObject", windll.kernel32),
226 AssignProcessToJobObjectFlags)
227 AssignProcessToJobObject.errcheck = ErrCheckBool
229 # GetCurrentProcess()
230 # because os.getPid() is way too easy
231 GetCurrentProcessProto = WINFUNCTYPE(HANDLE # Return type
232 )
233 GetCurrentProcessFlags = ()
234 GetCurrentProcess = GetCurrentProcessProto(
235 ("GetCurrentProcess", windll.kernel32),
236 GetCurrentProcessFlags)
237 GetCurrentProcess.errcheck = ErrCheckHandle
239 # IsProcessInJob()
240 try:
241 IsProcessInJobProto = WINFUNCTYPE(BOOL, # Return type
242 HANDLE, # Process Handle
243 HANDLE, # Job Handle
244 LPBOOL # Result
245 )
246 IsProcessInJobFlags = ((1, "ProcessHandle"),
247 (1, "JobHandle", HANDLE(0)),
248 (2, "Result"))
249 IsProcessInJob = IsProcessInJobProto(
250 ("IsProcessInJob", windll.kernel32),
251 IsProcessInJobFlags)
252 IsProcessInJob.errcheck = ErrCheckBool
253 except AttributeError:
254 # windows 2k doesn't have this API
255 def IsProcessInJob(process):
256 return False
259 # ResumeThread()
261 def ErrCheckResumeThread(result, func, args):
262 if result == -1:
263 raise WinError()
265 return args
267 ResumeThreadProto = WINFUNCTYPE(DWORD, # Return type
268 HANDLE # hThread
269 )
270 ResumeThreadFlags = ((1, "hThread"),)
271 ResumeThread = ResumeThreadProto(("ResumeThread", windll.kernel32),
272 ResumeThreadFlags)
273 ResumeThread.errcheck = ErrCheckResumeThread
275 # TerminateProcess()
277 TerminateProcessProto = WINFUNCTYPE(BOOL, # Return type
278 HANDLE, # hProcess
279 UINT # uExitCode
280 )
281 TerminateProcessFlags = ((1, "hProcess"),
282 (1, "uExitCode", 127))
283 TerminateProcess = TerminateProcessProto(
284 ("TerminateProcess", windll.kernel32),
285 TerminateProcessFlags)
286 TerminateProcess.errcheck = ErrCheckBool
288 # TerminateJobObject()
290 TerminateJobObjectProto = WINFUNCTYPE(BOOL, # Return type
291 HANDLE, # hJob
292 UINT # uExitCode
293 )
294 TerminateJobObjectFlags = ((1, "hJob"),
295 (1, "uExitCode", 127))
296 TerminateJobObject = TerminateJobObjectProto(
297 ("TerminateJobObject", windll.kernel32),
298 TerminateJobObjectFlags)
299 TerminateJobObject.errcheck = ErrCheckBool
301 # WaitForSingleObject()
303 WaitForSingleObjectProto = WINFUNCTYPE(DWORD, # Return type
304 HANDLE, # hHandle
305 DWORD, # dwMilliseconds
306 )
307 WaitForSingleObjectFlags = ((1, "hHandle"),
308 (1, "dwMilliseconds", -1))
309 WaitForSingleObject = WaitForSingleObjectProto(
310 ("WaitForSingleObject", windll.kernel32),
311 WaitForSingleObjectFlags)
313 INFINITE = -1
314 WAIT_TIMEOUT = 0x0102
315 WAIT_OBJECT_0 = 0x0
316 WAIT_ABANDONED = 0x0080
317 WAIT_FAILED = 0xFFFFFFFF
319 # GetExitCodeProcess()
321 GetExitCodeProcessProto = WINFUNCTYPE(BOOL, # Return type
322 HANDLE, # hProcess
323 LPDWORD, # lpExitCode
324 )
325 GetExitCodeProcessFlags = ((1, "hProcess"),
326 (2, "lpExitCode"))
327 GetExitCodeProcess = GetExitCodeProcessProto(
328 ("GetExitCodeProcess", windll.kernel32),
329 GetExitCodeProcessFlags)
330 GetExitCodeProcess.errcheck = ErrCheckBool
332 def CanCreateJobObject():
333 # Running firefox in a job (from cfx) hangs on sites using flash plugin
334 # so job creation is turned off for now. (see Bug 768651).
335 return False
337 ### testing functions
339 def parent():
340 print 'Starting parent'
341 currentProc = GetCurrentProcess()
342 if IsProcessInJob(currentProc):
343 print >> sys.stderr, "You should not be in a job object to test"
344 sys.exit(1)
345 assert CanCreateJobObject()
346 print 'File: %s' % __file__
347 command = [sys.executable, __file__, '-child']
348 print 'Running command: %s' % command
349 process = Popen(command)
350 process.kill()
351 code = process.returncode
352 print 'Child code: %s' % code
353 assert code == 127
355 def child():
356 print 'Starting child'
357 currentProc = GetCurrentProcess()
358 injob = IsProcessInJob(currentProc)
359 print "Is in a job?: %s" % injob
360 can_create = CanCreateJobObject()
361 print 'Can create job?: %s' % can_create
362 process = Popen('c:\\windows\\notepad.exe')
363 assert process._job
364 jobinfo = QueryInformationJobObject(process._job, 'JobObjectExtendedLimitInformation')
365 print 'Job info: %s' % jobinfo
366 limitflags = jobinfo['BasicLimitInformation']['LimitFlags']
367 print 'LimitFlags: %s' % limitflags
368 process.kill()
370 if __name__ == '__main__':
371 import sys
372 from killableprocess import Popen
373 nargs = len(sys.argv[1:])
374 if nargs:
375 if nargs != 1 or sys.argv[1] != '-child':
376 raise AssertionError('Wrong flags; run like `python /path/to/winprocess.py`')
377 child()
378 else:
379 parent()