VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/testdriver/winbase.py@ 70486

Last change on this file since 70486 was 69578, checked in by vboxsync, 7 years ago

better processExists() implementations for windows.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.6 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: winbase.py 69578 2017-11-04 10:19:34Z vboxsync $
3
4"""
5This module is here to externalize some Windows specifics that gives pychecker
6a hard time when running on non-Windows systems.
7"""
8
9__copyright__ = \
10"""
11Copyright (C) 2010-2017 Oracle Corporation
12
13This file is part of VirtualBox Open Source Edition (OSE), as
14available from http://www.virtualbox.org. This file is free software;
15you can redistribute it and/or modify it under the terms of the GNU
16General Public License (GPL) as published by the Free Software
17Foundation, in version 2 as it comes in the "COPYING" file of the
18VirtualBox OSE distribution. VirtualBox OSE is distributed in the
19hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
20
21The contents of this file may alternatively be used under the terms
22of the Common Development and Distribution License Version 1.0
23(CDDL) only, as it comes in the "COPYING.CDDL" file of the
24VirtualBox OSE distribution, in which case the provisions of the
25CDDL are applicable instead of those of the GPL.
26
27You may elect to license modified versions of this file under the
28terms and conditions of either the GPL or the CDDL or both.
29"""
30__version__ = "$Revision: 69578 $"
31
32
33# Standard Python imports.
34import os;
35import ctypes;
36
37# Windows specific imports.
38import win32api; # pylint: disable=import-error
39import win32con; # pylint: disable=import-error
40import win32console; # pylint: disable=import-error
41import win32event; # pylint: disable=import-error
42import win32process; # pylint: disable=import-error
43import winerror; # pylint: disable=import-error
44import pywintypes; # pylint: disable=import-error
45
46# Validation Kit imports.
47from testdriver import reporter;
48
49
50
51#
52# Windows specific implementation of base functions.
53#
54
55def processInterrupt(uPid):
56 """
57 The Windows version of base.processInterrupt
58
59 Note! This doesn't work terribly well with a lot of processes.
60 """
61 try:
62 # pylint: disable=no-member
63 win32console.GenerateConsoleCtrlEvent(win32con.CTRL_BREAK_EVENT, uPid);
64 #GenerateConsoleCtrlEvent = ctypes.windll.kernel32.GenerateConsoleCtrlEvent
65 #rc = GenerateConsoleCtrlEvent(1, uPid);
66 #reporter.log('GenerateConsoleCtrlEvent -> %s' % (rc,));
67 fRc = True;
68 except:
69 reporter.logXcpt('uPid=%s' % (uPid,));
70 fRc = False;
71 return fRc;
72
73def postThreadMesssageClose(uTid):
74 """ Posts a WM_CLOSE message to the specified thread."""
75 fRc = False;
76 try:
77 win32api.PostThreadMessage(uTid, win32con.WM_CLOSE, 0, 0); # pylint: disable=no-member
78 fRc = True;
79 except:
80 reporter.logXcpt('uTid=%s' % (uTid,));
81 return fRc;
82
83def postThreadMesssageQuit(uTid):
84 """ Posts a WM_QUIT message to the specified thread."""
85 fRc = False;
86 try:
87 win32api.PostThreadMessage(uTid, win32con.WM_QUIT, 0x40010004, 0); # DBG_TERMINATE_PROCESS # pylint: disable=no-member
88 fRc = True;
89 except:
90 reporter.logXcpt('uTid=%s' % (uTid,));
91 return fRc;
92
93def processTerminate(uPid):
94 """ The Windows version of base.processTerminate """
95 # pylint: disable=no-member
96 fRc = False;
97 try:
98 hProcess = win32api.OpenProcess(win32con.PROCESS_TERMINATE, False, uPid);
99 except:
100 reporter.logXcpt('uPid=%s' % (uPid,));
101 else:
102 try:
103 win32process.TerminateProcess(hProcess, 0x40010004); # DBG_TERMINATE_PROCESS
104 fRc = True;
105 except:
106 reporter.logXcpt('uPid=%s' % (uPid,));
107 hProcess.Close(); #win32api.CloseHandle(hProcess)
108 return fRc;
109
110def processKill(uPid):
111 """ The Windows version of base.processKill """
112 return processTerminate(uPid);
113
114def processExists(uPid):
115 """ The Windows version of base.processExists """
116 # We try open the process for waiting since this is generally only forbidden in a very few cases.
117 try:
118 hProcess = win32api.OpenProcess(win32con.SYNCHRONIZE, False, uPid); # pylint: disable=no-member
119 except pywintypes.error as oXcpt: # pylint: disable=no-member
120 if oXcpt.winerror == winerror.ERROR_INVALID_PARAMETER:
121 return False;
122 if oXcpt.winerror != winerror.ERROR_ACCESS_DENIED:
123 reporter.logXcpt('uPid=%s oXcpt=%s' % (uPid, oXcpt));
124 return False;
125 reporter.logXcpt('uPid=%s oXcpt=%s' % (uPid, oXcpt));
126 except Exception as oXcpt:
127 reporter.logXcpt('uPid=%s' % (uPid,));
128 return False;
129 else:
130 hProcess.Close(); #win32api.CloseHandle(hProcess)
131 return True;
132
133def processCheckPidAndName(uPid, sName):
134 """ The Windows version of base.processCheckPidAndName """
135 fRc = processExists(uPid);
136 if fRc is True:
137 try:
138 from win32com.client import GetObject; # pylint: disable=F0401
139 oWmi = GetObject('winmgmts:');
140 aoProcesses = oWmi.InstancesOf('Win32_Process');
141 for oProcess in aoProcesses:
142 if long(oProcess.Properties_("ProcessId").Value) == uPid:
143 sCurName = oProcess.Properties_("Name").Value;
144 reporter.log2('uPid=%s sName=%s sCurName=%s' % (uPid, sName, sCurName));
145 sName = sName.lower();
146 sCurName = sCurName.lower();
147 if os.path.basename(sName) == sName:
148 sCurName = os.path.basename(sCurName);
149
150 if sCurName == sName \
151 or sCurName + '.exe' == sName \
152 or sCurName == sName + '.exe':
153 fRc = True;
154 break;
155 except:
156 reporter.logXcpt('uPid=%s sName=%s' % (uPid, sName));
157 return fRc;
158
159#
160# Some helper functions.
161#
162def processCreate(sName, asArgs):
163 """
164 Returns a (pid, handle, tid) tuple on success. (-1, None) on failure (logged).
165 """
166
167 # Construct a command line.
168 sCmdLine = '';
169 for sArg in asArgs:
170 if sCmdLine == '':
171 sCmdLine += '"';
172 else:
173 sCmdLine += ' "';
174 sCmdLine += sArg;
175 sCmdLine += '"';
176
177 # Try start the process.
178 # pylint: disable=no-member
179 dwCreationFlags = win32con.CREATE_NEW_PROCESS_GROUP;
180 oStartupInfo = win32process.STARTUPINFO();
181 try:
182 (hProcess, hThread, uPid, uTid) = win32process.CreateProcess(sName,
183 sCmdLine, # CommandLine
184 None, # ProcessAttributes
185 None, # ThreadAttibutes
186 1, # fInheritHandles
187 dwCreationFlags,
188 None, # Environment
189 None, # CurrentDirectory.
190 oStartupInfo);
191 except:
192 reporter.logXcpt('sName="%s" sCmdLine="%s"' % (sName, sCmdLine));
193 return (-1, None, -1);
194
195 # Dispense with the thread handle.
196 try:
197 hThread.Close(); # win32api.CloseHandle(hThread);
198 except:
199 reporter.logXcpt();
200
201 # Try get full access to the process.
202 try:
203 hProcessFullAccess = win32api.DuplicateHandle(
204 win32api.GetCurrentProcess(),
205 hProcess,
206 win32api.GetCurrentProcess(),
207 win32con.PROCESS_TERMINATE
208 | win32con.PROCESS_QUERY_INFORMATION
209 | win32con.SYNCHRONIZE
210 | win32con.DELETE,
211 False,
212 0);
213 hProcess.Close(); # win32api.CloseHandle(hProcess);
214 hProcess = hProcessFullAccess;
215 except:
216 reporter.logXcpt();
217 reporter.log2('processCreate -> %#x, hProcess=%#x' % (uPid, hProcess,));
218 return (uPid, hProcess, uTid);
219
220def processPollByHandle(hProcess):
221 """
222 Polls the process handle to see if it has finished (True) or not (False).
223 """
224 try:
225 dwWait = win32event.WaitForSingleObject(hProcess, 0); # pylint: disable=no-member
226 except:
227 reporter.logXcpt('hProcess=%s %#x' % (hProcess, hProcess,));
228 return True;
229 return dwWait != win32con.WAIT_TIMEOUT; #0x102; #
230
231
232def processTerminateByHandle(hProcess):
233 """
234 Terminates the process.
235 """
236 try:
237 win32api.TerminateProcess(hProcess, 0x40010004); # DBG_TERMINATE_PROCESS # pylint: disable=no-member
238 except:
239 reporter.logXcpt('hProcess=%s %#x' % (hProcess, hProcess,));
240 return False;
241 return True;
242
243#
244# Misc
245#
246
247def logMemoryStats():
248 """
249 Logs windows memory stats.
250 """
251 class MemoryStatusEx(ctypes.Structure):
252 """ MEMORYSTATUSEX """
253 kaFields = [
254 ( 'dwLength', ctypes.c_ulong ),
255 ( 'dwMemoryLoad', ctypes.c_ulong ),
256 ( 'ullTotalPhys', ctypes.c_ulonglong ),
257 ( 'ullAvailPhys', ctypes.c_ulonglong ),
258 ( 'ullTotalPageFile', ctypes.c_ulonglong ),
259 ( 'ullAvailPageFile', ctypes.c_ulonglong ),
260 ( 'ullTotalVirtual', ctypes.c_ulonglong ),
261 ( 'ullAvailVirtual', ctypes.c_ulonglong ),
262 ( 'ullAvailExtendedVirtual', ctypes.c_ulonglong ),
263 ];
264 _fields_ = kaFields; # pylint: disable=invalid-name
265
266 def __init__(self):
267 super(MemoryStatusEx, self).__init__();
268 self.dwLength = ctypes.sizeof(self);
269
270 try:
271 oStats = MemoryStatusEx();
272 ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(oStats));
273 except:
274 reporter.logXcpt();
275 return False;
276
277 reporter.log('Memory statistics:');
278 for sField, _ in MemoryStatusEx.kaFields:
279 reporter.log(' %32s: %s' % (sField, getattr(oStats, sField)));
280 return True;
281
282def checkProcessHeap():
283 """
284 Calls HeapValidate(GetProcessHeap(), 0, NULL);
285 """
286
287 # Get the process heap.
288 try:
289 hHeap = ctypes.windll.kernel32.GetProcessHeap();
290 except:
291 reporter.logXcpt();
292 return False;
293
294 # Check it.
295 try:
296 fIsOkay = ctypes.windll.kernel32.HeapValidate(hHeap, 0, None);
297 except:
298 reporter.logXcpt();
299 return False;
300
301 if fIsOkay == 0:
302 reporter.log('HeapValidate failed!');
303
304 # Try trigger a dump using c:\utils\procdump64.exe.
305 from common import utils;
306
307 iPid = os.getpid();
308 asArgs = [ 'e:\\utils\\procdump64.exe', '-ma', '%s' % (iPid,), 'c:\\CrashDumps\\python.exe-%u-heap.dmp' % (iPid,)];
309 if utils.getHostArch() != 'amd64':
310 asArgs[0] = 'c:\\utils\\procdump.exe'
311 reporter.log('Trying to dump this process using: %s' % (asArgs,));
312 utils.processCall(asArgs);
313
314 # Generate a crash exception.
315 ctypes.windll.msvcrt.strcpy(None, None, 1024);
316
317 return True;
318
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette