summaryrefslogtreecommitdiff
path: root/sal/systools/win32/kill
diff options
context:
space:
mode:
authorRĂ¼diger Timm <rt@openoffice.org>2004-11-26 13:42:21 +0000
committerRĂ¼diger Timm <rt@openoffice.org>2004-11-26 13:42:21 +0000
commit447ce8dcb5e324b943ffea4252b8773f8f6231e0 (patch)
treef93fe0777e90d14121b6b1dfdd928ff40e5ba617 /sal/systools/win32/kill
parent7e716104c4debaab60d770c96e8488c93b2c8e17 (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/win32/kill')
-rw-r--r--sal/systools/win32/kill/kill.cxx448
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 000000000..6b2ff3b2c
--- /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;
+}
+