VirtualBox

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

Last change on this file since 79066 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.6 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: winbase.py 76553 2019-01-01 01:45:53Z 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-2019 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: 76553 $"
31
32
33# Standard Python imports.
34import ctypes;
35import os;
36import sys;
37
38# Windows specific imports.
39import pywintypes; # pylint: disable=import-error
40import winerror; # pylint: disable=import-error
41import win32con; # pylint: disable=import-error
42import win32api; # pylint: disable=import-error
43import win32console; # pylint: disable=import-error
44import win32event; # pylint: disable=import-error
45import win32process; # pylint: disable=import-error
46
47# Validation Kit imports.
48from testdriver import reporter;
49
50# Python 3 hacks:
51if sys.version_info[0] >= 3:
52 long = int; # pylint: disable=redefined-builtin,invalid-name
53
54
55#
56# Windows specific implementation of base functions.
57#
58
59def processInterrupt(uPid):
60 """
61 The Windows version of base.processInterrupt
62
63 Note! This doesn't work terribly well with a lot of processes.
64 """
65 try:
66 # pylint: disable=no-member
67 win32console.GenerateConsoleCtrlEvent(win32con.CTRL_BREAK_EVENT, uPid); # pylint: disable=c-extension-no-member
68 #GenerateConsoleCtrlEvent = ctypes.windll.kernel32.GenerateConsoleCtrlEvent
69 #rc = GenerateConsoleCtrlEvent(1, uPid);
70 #reporter.log('GenerateConsoleCtrlEvent -> %s' % (rc,));
71 fRc = True;
72 except:
73 reporter.logXcpt('uPid=%s' % (uPid,));
74 fRc = False;
75 return fRc;
76
77def postThreadMesssageClose(uTid):
78 """ Posts a WM_CLOSE message to the specified thread."""
79 fRc = False;
80 try:
81 win32api.PostThreadMessage(uTid, win32con.WM_CLOSE, 0, 0); # pylint: disable=no-member,c-extension-no-member
82 fRc = True;
83 except:
84 reporter.logXcpt('uTid=%s' % (uTid,));
85 return fRc;
86
87def postThreadMesssageQuit(uTid):
88 """ Posts a WM_QUIT message to the specified thread."""
89 fRc = False;
90 try:
91 win32api.PostThreadMessage(uTid, win32con.WM_QUIT, # pylint: disable=no-member,c-extension-no-member
92 0x40010004, 0); # DBG_TERMINATE_PROCESS
93 fRc = True;
94 except:
95 reporter.logXcpt('uTid=%s' % (uTid,));
96 return fRc;
97
98def processTerminate(uPid):
99 """ The Windows version of base.processTerminate """
100 # pylint: disable=no-member
101 fRc = False;
102 try:
103 hProcess = win32api.OpenProcess(win32con.PROCESS_TERMINATE, # pylint: disable=no-member,c-extension-no-member
104 False, uPid);
105 except:
106 reporter.logXcpt('uPid=%s' % (uPid,));
107 else:
108 try:
109 win32process.TerminateProcess(hProcess, # pylint: disable=no-member,c-extension-no-member
110 0x40010004); # DBG_TERMINATE_PROCESS
111 fRc = True;
112 except:
113 reporter.logXcpt('uPid=%s' % (uPid,));
114 hProcess.Close(); #win32api.CloseHandle(hProcess)
115 return fRc;
116
117def processKill(uPid):
118 """ The Windows version of base.processKill """
119 return processTerminate(uPid);
120
121def processExists(uPid):
122 """ The Windows version of base.processExists """
123 # We try open the process for waiting since this is generally only forbidden in a very few cases.
124 try:
125 hProcess = win32api.OpenProcess(win32con.SYNCHRONIZE, False, uPid); # pylint: disable=no-member,c-extension-no-member
126 except pywintypes.error as oXcpt: # pylint: disable=no-member
127 if oXcpt.winerror == winerror.ERROR_INVALID_PARAMETER:
128 return False;
129 if oXcpt.winerror != winerror.ERROR_ACCESS_DENIED:
130 reporter.logXcpt('uPid=%s oXcpt=%s' % (uPid, oXcpt));
131 return False;
132 reporter.logXcpt('uPid=%s oXcpt=%s' % (uPid, oXcpt));
133 except Exception as oXcpt:
134 reporter.logXcpt('uPid=%s' % (uPid,));
135 return False;
136 else:
137 hProcess.Close(); #win32api.CloseHandle(hProcess)
138 return True;
139
140def processCheckPidAndName(uPid, sName):
141 """ The Windows version of base.processCheckPidAndName """
142 fRc = processExists(uPid);
143 if fRc is True:
144 try:
145 from win32com.client import GetObject; # pylint: disable=F0401
146 oWmi = GetObject('winmgmts:');
147 aoProcesses = oWmi.InstancesOf('Win32_Process');
148 for oProcess in aoProcesses:
149 if long(oProcess.Properties_("ProcessId").Value) == uPid:
150 sCurName = oProcess.Properties_("Name").Value;
151 reporter.log2('uPid=%s sName=%s sCurName=%s' % (uPid, sName, sCurName));
152 sName = sName.lower();
153 sCurName = sCurName.lower();
154 if os.path.basename(sName) == sName:
155 sCurName = os.path.basename(sCurName);
156
157 if sCurName == sName \
158 or sCurName + '.exe' == sName \
159 or sCurName == sName + '.exe':
160 fRc = True;
161 break;
162 except:
163 reporter.logXcpt('uPid=%s sName=%s' % (uPid, sName));
164 return fRc;
165
166#
167# Some helper functions.
168#
169def processCreate(sName, asArgs):
170 """
171 Returns a (pid, handle, tid) tuple on success. (-1, None) on failure (logged).
172 """
173
174 # Construct a command line.
175 sCmdLine = '';
176 for sArg in asArgs:
177 if sCmdLine == '':
178 sCmdLine += '"';
179 else:
180 sCmdLine += ' "';
181 sCmdLine += sArg;
182 sCmdLine += '"';
183
184 # Try start the process.
185 # pylint: disable=no-member
186 dwCreationFlags = win32con.CREATE_NEW_PROCESS_GROUP;
187 oStartupInfo = win32process.STARTUPINFO(); # pylint: disable=c-extension-no-member
188 try:
189 (hProcess, hThread, uPid, uTid) = win32process.CreateProcess(sName, # pylint: disable=c-extension-no-member
190 sCmdLine, # CommandLine
191 None, # ProcessAttributes
192 None, # ThreadAttibutes
193 1, # fInheritHandles
194 dwCreationFlags,
195 None, # Environment
196 None, # CurrentDirectory.
197 oStartupInfo);
198 except:
199 reporter.logXcpt('sName="%s" sCmdLine="%s"' % (sName, sCmdLine));
200 return (-1, None, -1);
201
202 # Dispense with the thread handle.
203 try:
204 hThread.Close(); # win32api.CloseHandle(hThread);
205 except:
206 reporter.logXcpt();
207
208 # Try get full access to the process.
209 try:
210 hProcessFullAccess = win32api.DuplicateHandle( # pylint: disable=c-extension-no-member
211 win32api.GetCurrentProcess(), # pylint: disable=c-extension-no-member
212 hProcess,
213 win32api.GetCurrentProcess(), # pylint: disable=c-extension-no-member
214 win32con.PROCESS_TERMINATE
215 | win32con.PROCESS_QUERY_INFORMATION
216 | win32con.SYNCHRONIZE
217 | win32con.DELETE,
218 False,
219 0);
220 hProcess.Close(); # win32api.CloseHandle(hProcess);
221 hProcess = hProcessFullAccess;
222 except:
223 reporter.logXcpt();
224 reporter.log2('processCreate -> %#x, hProcess=%s %#x' % (uPid, hProcess, hProcess.handle,));
225 return (uPid, hProcess, uTid);
226
227def processPollByHandle(hProcess):
228 """
229 Polls the process handle to see if it has finished (True) or not (False).
230 """
231 try:
232 dwWait = win32event.WaitForSingleObject(hProcess, 0); # pylint: disable=no-member,c-extension-no-member
233 except:
234 reporter.logXcpt('hProcess=%s %#x' % (hProcess, hProcess.handle,));
235 return True;
236 return dwWait != win32con.WAIT_TIMEOUT; #0x102; #
237
238
239def processTerminateByHandle(hProcess):
240 """
241 Terminates the process.
242 """
243 try:
244 win32api.TerminateProcess(hProcess, # pylint: disable=no-member,c-extension-no-member
245 0x40010004); # DBG_TERMINATE_PROCESS
246 except:
247 reporter.logXcpt('hProcess=%s %#x' % (hProcess, hProcess.handle,));
248 return False;
249 return True;
250
251#
252# Misc
253#
254
255def logMemoryStats():
256 """
257 Logs windows memory stats.
258 """
259 class MemoryStatusEx(ctypes.Structure):
260 """ MEMORYSTATUSEX """
261 kaFields = [
262 ( 'dwLength', ctypes.c_ulong ),
263 ( 'dwMemoryLoad', ctypes.c_ulong ),
264 ( 'ullTotalPhys', ctypes.c_ulonglong ),
265 ( 'ullAvailPhys', ctypes.c_ulonglong ),
266 ( 'ullTotalPageFile', ctypes.c_ulonglong ),
267 ( 'ullAvailPageFile', ctypes.c_ulonglong ),
268 ( 'ullTotalVirtual', ctypes.c_ulonglong ),
269 ( 'ullAvailVirtual', ctypes.c_ulonglong ),
270 ( 'ullAvailExtendedVirtual', ctypes.c_ulonglong ),
271 ];
272 _fields_ = kaFields; # pylint: disable=invalid-name
273
274 def __init__(self):
275 super(MemoryStatusEx, self).__init__();
276 self.dwLength = ctypes.sizeof(self);
277
278 try:
279 oStats = MemoryStatusEx();
280 ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(oStats));
281 except:
282 reporter.logXcpt();
283 return False;
284
285 reporter.log('Memory statistics:');
286 for sField, _ in MemoryStatusEx.kaFields:
287 reporter.log(' %32s: %s' % (sField, getattr(oStats, sField)));
288 return True;
289
290def checkProcessHeap():
291 """
292 Calls HeapValidate(GetProcessHeap(), 0, NULL);
293 """
294
295 # Get the process heap.
296 try:
297 hHeap = ctypes.windll.kernel32.GetProcessHeap();
298 except:
299 reporter.logXcpt();
300 return False;
301
302 # Check it.
303 try:
304 fIsOkay = ctypes.windll.kernel32.HeapValidate(hHeap, 0, None);
305 except:
306 reporter.logXcpt();
307 return False;
308
309 if fIsOkay == 0:
310 reporter.log('HeapValidate failed!');
311
312 # Try trigger a dump using c:\utils\procdump64.exe.
313 from common import utils;
314
315 iPid = os.getpid();
316 asArgs = [ 'e:\\utils\\procdump64.exe', '-ma', '%s' % (iPid,), 'c:\\CrashDumps\\python.exe-%u-heap.dmp' % (iPid,)];
317 if utils.getHostArch() != 'amd64':
318 asArgs[0] = 'c:\\utils\\procdump.exe'
319 reporter.log('Trying to dump this process using: %s' % (asArgs,));
320 utils.processCall(asArgs);
321
322 # Generate a crash exception.
323 ctypes.windll.msvcrt.strcpy(None, None, 1024);
324
325 return True;
326
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