summaryrefslogtreecommitdiff
path: root/sal/systools/win32/kill/kill.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sal/systools/win32/kill/kill.cxx')
-rw-r--r--sal/systools/win32/kill/kill.cxx443
1 files changed, 443 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..dd7ae85a0af2
--- /dev/null
+++ b/sal/systools/win32/kill/kill.cxx
@@ -0,0 +1,443 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+#include <tchar.h>
+
+#ifdef _MSC_VER
+#pragma warning(push,1) // disable warnings within system headers
+#endif
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <tlhelp32.h>
+#include <psapi.h>
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+#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>
+
+#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 BOOL RaiseSignalEx( HANDLE hProcess, int sig )
+{
+ DWORD dwProcessId = GetProcessId( hProcess );
+
+ HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
+ HANDLE hThread = 0;
+ BOOL fSuccess = FALSE;
+
+ if ( IsValidHandle(hSnapshot) )
+ {
+ THREADENTRY32 te;
+
+ te.dwSize = sizeof(te);
+ fSuccess = Thread32First( hSnapshot, &te );
+ while ( fSuccess )
+ {
+ if ( te.th32OwnerProcessID == dwProcessId )
+ {
+ hThread = OpenThread(
+ THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION |
+ THREAD_GET_CONTEXT | THREAD_SET_CONTEXT,
+ FALSE, te.th32ThreadID );
+ if ( IsValidHandle(hThread) )
+ break;
+ }
+
+ fSuccess = Thread32Next( hSnapshot, &te );
+ }
+
+ CloseHandle( hSnapshot );
+ }
+
+ if ( fSuccess )
+ {
+ CONTEXT aContext;
+
+ if ( SuspendThread( hThread ) != (DWORD)-1 )
+ {
+ ZeroMemory( &aContext, sizeof(aContext) );
+ aContext.ContextFlags = CONTEXT_FULL;
+
+ fSuccess = GetThreadContext( hThread, &aContext );
+
+ if ( fSuccess )
+ {
+ 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;
+ }
+
+ fSuccess = SetThreadContext( hThread, &aContext );
+ }
+
+ fSuccess = ResumeThread( hThread ) && fSuccess;
+
+ DWORD dwLastError = GetLastError();
+ CloseHandle( hThread );
+ SetLastError( dwLastError );
+
+ return fSuccess;
+ }
+ }
+
+ return FALSE;
+}
+/////////////////////////////////////////////////////////////////////////////
+// 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 ) == static_cast< unsigned >(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 );
+ }
+
+}
+
+void OutputSystemMessage( DWORD dwErrorCode )
+{
+ LPVOID lpMsgBuf;
+ FormatMessageA(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ dwErrorCode,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPSTR)&lpMsgBuf,
+ 0,
+ NULL
+ );
+
+ printf( (LPSTR)lpMsgBuf );
+ LocalFree( lpMsgBuf );
+}
+
+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 ) )
+ {
+ if ( SIGKILL == sig )
+ TerminateProcess( hProcess, 255 );
+ else
+ {
+ if ( RaiseSignalEx( hProcess, sig ) )
+ _tprintf( _T("OK\n") );
+ else
+ {
+ OutputSystemMessage( GetLastError() );
+ }
+ }
+
+ CloseHandle( hProcess );
+ }
+ else
+ {
+ OutputSystemMessage( GetLastError() );
+ }
+ }
+
+ return 0;
+}
+