diff options
author | Rüdiger Timm <rt@openoffice.org> | 2004-11-26 13:42:21 +0000 |
---|---|---|
committer | Rüdiger Timm <rt@openoffice.org> | 2004-11-26 13:42:21 +0000 |
commit | cdc478b7da1523ebe8af909868af3fa360a7ef82 (patch) | |
tree | d2c747e8acb475a377af3067afeb96d072100227 /sal/systools | |
parent | 50f73297226cecb46dcefb68afbff8cbd01a7855 (diff) |
INTEGRATION: CWS recovery04 (1.1.2); FILE ADDED
2004/11/02 11:18:51 hro 1.1.2.1: #i36457# Kill command line tool for Windows crash report testing
Diffstat (limited to 'sal/systools')
-rw-r--r-- | sal/systools/win32/kill/kill.cxx | 448 |
1 files changed, 448 insertions, 0 deletions
diff --git a/sal/systools/win32/kill/kill.cxx b/sal/systools/win32/kill/kill.cxx new file mode 100644 index 000000000000..e3c58fb5673b --- /dev/null +++ b/sal/systools/win32/kill/kill.cxx @@ -0,0 +1,448 @@ +//************************************************************************* +// +// $RCSfile: kill.cxx,v $ +// +// $Revision: 1.2 $ +// +// last change: $Author: rt $ $Date: 2004-11-26 14:42:21 $ +// +// The Contents of this file are made available subject to the terms of +// either of the following licenses +// +// - GNU Lesser General Public License Version 2.1 +// - Sun Industry Standards Source License Version 1.1 +// +// Sun Microsystems Inc., October, 2000 +// +// GNU Lesser General Public License Version 2.1 +// ============================================= +// Copyright 2000 by Sun Microsystems, Inc. +// 901 San Antonio Road, Palo Alto, CA 94303, USA +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License version 2.1, as published by the Free Software Foundation. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, +// MA 02111-1307 USA +// +// +// Sun Industry Standards Source License Version 1.1 +// ================================================= +// The contents of this file are subject to the Sun Industry Standards +// Source License Version 1.1 (the "License"); You may not use this file +// except in compliance with the License. You may obtain a copy of the +// License at http://www.openoffice.org/license.html. +// +// Software provided under this License is provided on an "AS IS" basis, +// WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, +// WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, +// MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. +// See the License for the specific provisions governing your rights and +// obligations concerning the Software. +// +// The Initial Developer of the Original Code is: Sun Microsystems, Inc. +// +// Copyright: 2000 by Sun Microsystems, Inc. +// +// All Rights Reserved. +// +// Contributor(s): _______________________________________ +// +// +// +//************************************************************************* + +#include <tchar.h> + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <tlhelp32.h> +#include <psapi.h> + +#include <signal.h> +#include <stdarg.h> +#include <stdlib.h> +#include <stdio.h> + +#ifndef SIGNULL +#define SIGNULL 0 +#endif + +#ifndef SIGKILL +#define SIGKILL 9 +#endif + +#include <signal.h> + +///////////////////////////////////////////////////////////////////////////// +// Converts a signal to an exception and raises it +///////////////////////////////////////////////////////////////////////////// + +static DWORD GetExceptionCodeForSignal( int sig ) +{ + DWORD dwExceptionCode = 0; + + switch ( sig ) + { + case SIGSEGV: + dwExceptionCode = EXCEPTION_ACCESS_VIOLATION; + break; + case SIGFPE: + dwExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO; + break; + case SIGILL: + dwExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; + break; + case SIGBREAK: + dwExceptionCode = EXCEPTION_BREAKPOINT; + break; + case SIGINT: + dwExceptionCode = CONTROL_C_EXIT; + break; + } + + return dwExceptionCode; +} + + +#define MAX_MODULES 1024 + +///////////////////////////////////////////////////////////////////////////// +// Determines if a returned handle value is valid +///////////////////////////////////////////////////////////////////////////// + +static inline bool IsValidHandle( HANDLE handle ) +{ + return INVALID_HANDLE_VALUE != handle && NULL != handle; +} + + +#define elementsof( a ) (sizeof(a) / sizeof( (a)[0] )) + +///////////////////////////////////////////////////////////////////////////// +// Retrieves function adress in another process +///////////////////////////////////////////////////////////////////////////// + +#if 1 +#define GetProcAddressEx( hProcess, hModule, lpProcName ) GetProcAddress( hModule, lpProcName ) +#else +FARPROC WINAPI GetProcAddressEx( HANDLE hProcess, HMODULE hModule, LPCSTR lpProcName ) +{ + FARPROC lpfnProcAddress = GetProcAddress( hModule, lpProcName ); + + if ( lpfnProcAddress ) + { + DWORD dwProcessId = GetProcessId( hProcess ); + + if ( GetCurrentProcessId() != dwProcessId ) + { + FARPROC lpfnRemoteProcAddress = NULL; + TCHAR szBaseName[MAX_PATH]; + + if ( GetModuleBaseName( GetCurrentProcess(), hModule, szBaseName, elementsof(szBaseName) ) ) + { + HMODULE ahModules[MAX_MODULES]; + DWORD cbNeeded = 0; + + if ( EnumProcessModules( hProcess, ahModules, sizeof(ahModules), &cbNeeded ) ) + { + ULONG nModules = cbNeeded / sizeof(ahModules[0]); + + for ( ULONG n = 0; n < nModules; n++ ) + { + TCHAR szRemoteBaseName[MAX_PATH]; + + if ( GetModuleBaseName( + hProcess, ahModules[n], szRemoteBaseName, elementsof(szRemoteBaseName) ) && + 0 == lstrcmpi( szRemoteBaseName, szBaseName ) + ) + { + lpfnRemoteProcAddress = lpfnProcAddress; + + if ( ahModules[n] != hModule ) + *(LPBYTE*)&lpfnRemoteProcAddress += (LPBYTE)ahModules[n] - (LPBYTE)hModule; + break; + } + } + } + } + + lpfnProcAddress = lpfnRemoteProcAddress; + } + } + + return lpfnProcAddress; +} +#endif + +///////////////////////////////////////////////////////////////////////////// +// Raises a signal in an other process +///////////////////////////////////////////////////////////////////////////// + +static DWORD SignalToExceptionCode( int signal ) +{ + switch ( signal ) + { + case SIGSEGV: + return EXCEPTION_ACCESS_VIOLATION; + case SIGFPE: + return EXCEPTION_FLT_INVALID_OPERATION; + case SIGILL: + return EXCEPTION_ILLEGAL_INSTRUCTION; + case SIGINT: + return CONTROL_C_EXIT; + case SIGBREAK: + return CONTROL_C_EXIT; + default: + return 0; + } +} + +static void RaiseSignalEx( HANDLE hProcess, int sig ) +{ + DWORD dwProcessId = GetProcessId( hProcess ); + + HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 ); + HANDLE hThread = 0; + + if ( IsValidHandle(hSnapshot) ) + { + THREADENTRY32 te; + + te.dwSize = sizeof(te); + BOOL fSuccess = Thread32First( hSnapshot, &te ); + while ( fSuccess ) + { + if ( te.th32OwnerProcessID == dwProcessId ) + { + hThread = OpenThread( THREAD_ALL_ACCESS, FALSE, te.th32ThreadID ); + break; + } + + fSuccess = Thread32Next( hSnapshot, &te ); + } + + CloseHandle( hSnapshot ); + } + + CONTEXT aContext; + + SuspendThread( hThread ); + ZeroMemory( &aContext, sizeof(aContext) ); + aContext.ContextFlags = CONTEXT_FULL; + GetThreadContext( hThread, &aContext ); + + if ( sig ) + { + DWORD dwStackBuffer[] = + { + aContext.Eip, + SignalToExceptionCode( sig ), + EXCEPTION_NONCONTINUABLE, + 0, + 0 + }; + + aContext.Esp -= sizeof(dwStackBuffer); + WriteProcessMemory( hProcess, (LPVOID)aContext.Esp, dwStackBuffer, sizeof(dwStackBuffer), NULL ); + aContext.Eip = (DWORD)GetProcAddressEx( hProcess, GetModuleHandleA("KERNEL32"), "RaiseException" ); + } + else + { + aContext.Ecx = aContext.Eax = aContext.Ebx = aContext.Edx = aContext.Esi = aContext.Edi = 0; + } + + SetThreadContext( hThread, &aContext ); + ResumeThread( hThread ); +} +///////////////////////////////////////////////////////////////////////////// +// Command line parameter parsing +///////////////////////////////////////////////////////////////////////////// + +static void ParseCommandArgs( LPDWORD lpProcesses, LPDWORD lpdwNumProcesses, int *pSig ) +{ + typedef struct _SignalEntry + { + LPCTSTR lpSignalName; + int iSignalValue; + } SignalEntry; + + #define SIG_ENTRY( signal ) { TEXT(#signal), SIG##signal } + + static SignalEntry SupportedSignals[] = + { + SIG_ENTRY( NULL ), + SIG_ENTRY( SEGV ), + SIG_ENTRY( ILL ), + SIG_ENTRY( FPE ), + SIG_ENTRY( INT ), + SIG_ENTRY( BREAK ), + SIG_ENTRY( TERM ), + SIG_ENTRY( ABRT ), + SIG_ENTRY( KILL ) + }; + + const int NumSupportedSignals = elementsof(SupportedSignals); + + DWORD dwMaxProcesses = *lpdwNumProcesses; + int argc = __argc; + TCHAR **argv = __targv; + + *lpdwNumProcesses = 0; + + for ( int argn = 1; argn < argc; argn++ ) + { + if ( 0 == lstrcmpi( argv[argn], TEXT("-l") ) || + 0 == lstrcmpi( argv[argn], TEXT("/l") ) ) + + { + for ( int n = 0; n < NumSupportedSignals; n++ ) + { + _tprintf( _T("%s "), SupportedSignals[n] ); + } + _tprintf( _T("\n") ); + ExitProcess( 0 ); + } + else if ( 0 == lstrcmpi( argv[argn], TEXT("-?") ) || + 0 == lstrcmpi( argv[argn], TEXT("/?") ) || + 0 == lstrcmpi( argv[argn], TEXT("-h") ) || + 0 == lstrcmpi( argv[argn], TEXT("/h") ) || + 0 == lstrcmpi( argv[argn], TEXT("--help") ) ) + { + _tprintf( + _T("Terminates a process by sending a signal.\n\n") + _T("Usage: kill [ -l ] [ -signal ] pid ...\n\n") + _T("-l Lists supported signals\n") + _T("-signal Sends the specified signal to the given processes.\n") + _T(" signal can be a numeric value specifying the signal number\n") + _T(" or a string listed by the -l parameter. If no signal is\n") + _T(" given SIGTERM (-TERM) is used.\n") + _T("pid Process id(s) or executables names(s) of processes to \n") + _T(" signal or terminate.\n\n") + ); + ExitProcess( 0 ); + } + else if ( argv[argn] && ( *argv[argn] == '-' || *argv[argn] == '/' ) ) + { + LPCTSTR argsig = CharNext( argv[argn] ); + + int n; + for ( n = 0; n < NumSupportedSignals; n++ ) + { + _TCHAR *endptr = NULL; + + if ( 0 == lstrcmpi( SupportedSignals[n].lpSignalName, argsig ) || + _tcstoul( argsig, &endptr, 0 ) == SupportedSignals[n].iSignalValue && (!endptr || !*endptr) ) + { + *pSig = SupportedSignals[n].iSignalValue; + break; + } + } + + if ( n >= NumSupportedSignals ) + { + _ftprintf( stderr, + _T("kill: Illegal argument %s\n") + _T("Type 'kill --help' to show allowed syntax.\n") + _T("Type 'kill -l' to show supported signals.\n"), + argv[argn] ); + ExitProcess( 0 ); + } + } + else + { + unsigned long value = 0; + _TCHAR *endptr = NULL; + + value = _tcstoul( argv[argn], &endptr, 0 ); + + if ( !endptr || !*endptr ) + { + if ( *lpdwNumProcesses < dwMaxProcesses ) + { + *(lpProcesses++) = value; + (*lpdwNumProcesses)++; + } + } + else + { + HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); + + if ( IsValidHandle( hSnapshot ) ) + { + PROCESSENTRY32 pe; + + pe.dwSize = sizeof(pe); + BOOL fSuccess = Process32First( hSnapshot, &pe ); + + while ( fSuccess ) + { + if ( 0 == lstrcmpi( argv[argn], pe.szExeFile ) ) + { + if ( *lpdwNumProcesses < dwMaxProcesses ) + { + *(lpProcesses++) = pe.th32ProcessID; + (*lpdwNumProcesses)++; + } + } + fSuccess = Process32Next( hSnapshot, &pe ); + } + + CloseHandle( hSnapshot ); + } + } + } + } + + if ( !*lpdwNumProcesses ) + { + _ftprintf( stderr, + _T("kill: No process specified.\n") + _T("Use kill --help to show allowed syntax.\n") + ); + ExitProcess( 0 ); + } + +} + + +int _tmain() +{ + DWORD dwProcessIds[1024]; + DWORD nProcesses = elementsof(dwProcessIds); + int sig = SIGTERM; + + + ParseCommandArgs( dwProcessIds, &nProcesses, &sig ); + + for ( ULONG n = 0; n < nProcesses; n++ ) + { + HANDLE hProcess; + + _tprintf( _T("Sending signal to process id %d..."), dwProcessIds[n] ); + hProcess = OpenProcess( PROCESS_TERMINATE | PROCESS_CREATE_THREAD | SYNCHRONIZE | + PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, + FALSE, dwProcessIds[n] ); + + if ( IsValidHandle( hProcess ) ) + { + RaiseSignalEx( hProcess, sig ); + _tprintf( _T("Done\n") ); + + CloseHandle( hProcess ); + } + else + _ftprintf( stderr, _T("No such process\n") ); + } + + return 0; +} + |