merge the formfield patch from ooo-build
[ooovba.git] / sal / systools / win32 / kill / kill.cxx
blob1089746e98e5a681a4c2325799b694c2698cd0c7
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: kill.cxx,v $
10 * $Revision: 1.9 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sal.hxx"
34 #include <tchar.h>
36 #ifdef _MSC_VER
37 #pragma warning(push,1) // disable warnings within system headers
38 #endif
39 #define WIN32_LEAN_AND_MEAN
40 #include <windows.h>
41 #include <tlhelp32.h>
42 #include <psapi.h>
43 #ifdef _MSC_VER
44 #pragma warning(pop)
45 #endif
47 #include <signal.h>
48 #include <stdarg.h>
49 #include <stdlib.h>
50 #include <stdio.h>
52 #ifndef SIGNULL
53 #define SIGNULL 0
54 #endif
56 #ifndef SIGKILL
57 #define SIGKILL 9
58 #endif
60 #include <signal.h>
62 #define MAX_MODULES 1024
64 /////////////////////////////////////////////////////////////////////////////
65 // Determines if a returned handle value is valid
66 /////////////////////////////////////////////////////////////////////////////
68 static inline bool IsValidHandle( HANDLE handle )
70 return INVALID_HANDLE_VALUE != handle && NULL != handle;
74 #define elementsof( a ) (sizeof(a) / sizeof( (a)[0] ))
76 /////////////////////////////////////////////////////////////////////////////
77 // Retrieves function adress in another process
78 /////////////////////////////////////////////////////////////////////////////
80 #if 1
81 #define GetProcAddressEx( hProcess, hModule, lpProcName ) GetProcAddress( hModule, lpProcName )
82 #else
83 FARPROC WINAPI GetProcAddressEx( HANDLE hProcess, HMODULE hModule, LPCSTR lpProcName )
85 FARPROC lpfnProcAddress = GetProcAddress( hModule, lpProcName );
87 if ( lpfnProcAddress )
89 DWORD dwProcessId = GetProcessId( hProcess );
91 if ( GetCurrentProcessId() != dwProcessId )
93 FARPROC lpfnRemoteProcAddress = NULL;
94 TCHAR szBaseName[MAX_PATH];
96 if ( GetModuleBaseName( GetCurrentProcess(), hModule, szBaseName, elementsof(szBaseName) ) )
98 HMODULE ahModules[MAX_MODULES];
99 DWORD cbNeeded = 0;
101 if ( EnumProcessModules( hProcess, ahModules, sizeof(ahModules), &cbNeeded ) )
103 ULONG nModules = cbNeeded / sizeof(ahModules[0]);
105 for ( ULONG n = 0; n < nModules; n++ )
107 TCHAR szRemoteBaseName[MAX_PATH];
109 if ( GetModuleBaseName(
110 hProcess, ahModules[n], szRemoteBaseName, elementsof(szRemoteBaseName) ) &&
111 0 == lstrcmpi( szRemoteBaseName, szBaseName )
114 lpfnRemoteProcAddress = lpfnProcAddress;
116 if ( ahModules[n] != hModule )
117 *(LPBYTE*)&lpfnRemoteProcAddress += (LPBYTE)ahModules[n] - (LPBYTE)hModule;
118 break;
124 lpfnProcAddress = lpfnRemoteProcAddress;
128 return lpfnProcAddress;
130 #endif
132 /////////////////////////////////////////////////////////////////////////////
133 // Raises a signal in an other process
134 /////////////////////////////////////////////////////////////////////////////
136 static DWORD SignalToExceptionCode( int signal )
138 switch ( signal )
140 case SIGSEGV:
141 return EXCEPTION_ACCESS_VIOLATION;
142 case SIGFPE:
143 return EXCEPTION_FLT_INVALID_OPERATION;
144 case SIGILL:
145 return EXCEPTION_ILLEGAL_INSTRUCTION;
146 case SIGINT:
147 return CONTROL_C_EXIT;
148 case SIGBREAK:
149 return CONTROL_C_EXIT;
150 default:
151 return 0;
155 static BOOL RaiseSignalEx( HANDLE hProcess, int sig )
157 DWORD dwProcessId = GetProcessId( hProcess );
159 HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
160 HANDLE hThread = 0;
161 BOOL fSuccess = FALSE;
163 if ( IsValidHandle(hSnapshot) )
165 THREADENTRY32 te;
167 te.dwSize = sizeof(te);
168 fSuccess = Thread32First( hSnapshot, &te );
169 while ( fSuccess )
171 if ( te.th32OwnerProcessID == dwProcessId )
173 hThread = OpenThread(
174 THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION |
175 THREAD_GET_CONTEXT | THREAD_SET_CONTEXT,
176 FALSE, te.th32ThreadID );
177 if ( IsValidHandle(hThread) )
178 break;
181 fSuccess = Thread32Next( hSnapshot, &te );
184 CloseHandle( hSnapshot );
187 if ( fSuccess )
189 CONTEXT aContext;
191 if ( SuspendThread( hThread ) != (DWORD)-1 )
193 ZeroMemory( &aContext, sizeof(aContext) );
194 aContext.ContextFlags = CONTEXT_FULL;
196 fSuccess = GetThreadContext( hThread, &aContext );
198 if ( fSuccess )
200 if ( sig )
202 DWORD dwStackBuffer[] =
204 aContext.Eip,
205 SignalToExceptionCode( sig ),
206 EXCEPTION_NONCONTINUABLE,
211 aContext.Esp -= sizeof(dwStackBuffer);
212 WriteProcessMemory( hProcess, (LPVOID)aContext.Esp, dwStackBuffer, sizeof(dwStackBuffer), NULL );
213 aContext.Eip = (DWORD)GetProcAddressEx( hProcess, GetModuleHandleA("KERNEL32"), "RaiseException" );
215 else
217 aContext.Ecx = aContext.Eax = aContext.Ebx = aContext.Edx = aContext.Esi = aContext.Edi = 0;
220 fSuccess = SetThreadContext( hThread, &aContext );
223 fSuccess = ResumeThread( hThread ) && fSuccess;
225 DWORD dwLastError = GetLastError();
226 CloseHandle( hThread );
227 SetLastError( dwLastError );
229 return fSuccess;
233 return FALSE;
235 /////////////////////////////////////////////////////////////////////////////
236 // Command line parameter parsing
237 /////////////////////////////////////////////////////////////////////////////
239 static void ParseCommandArgs( LPDWORD lpProcesses, LPDWORD lpdwNumProcesses, int *pSig )
241 typedef struct _SignalEntry
243 LPCTSTR lpSignalName;
244 int iSignalValue;
245 } SignalEntry;
247 #define SIG_ENTRY( signal ) { TEXT(#signal), SIG##signal }
249 static SignalEntry SupportedSignals[] =
251 SIG_ENTRY( NULL ),
252 SIG_ENTRY( SEGV ),
253 SIG_ENTRY( ILL ),
254 SIG_ENTRY( FPE ),
255 SIG_ENTRY( INT ),
256 SIG_ENTRY( BREAK ),
257 SIG_ENTRY( TERM ),
258 SIG_ENTRY( ABRT ),
259 SIG_ENTRY( KILL )
262 const int NumSupportedSignals = elementsof(SupportedSignals);
264 DWORD dwMaxProcesses = *lpdwNumProcesses;
265 int argc = __argc;
266 TCHAR **argv = __targv;
268 *lpdwNumProcesses = 0;
270 for ( int argn = 1; argn < argc; argn++ )
272 if ( 0 == lstrcmpi( argv[argn], TEXT("-l") ) ||
273 0 == lstrcmpi( argv[argn], TEXT("/l") ) )
276 for ( int n = 0; n < NumSupportedSignals; n++ )
278 _tprintf( _T("%s "), SupportedSignals[n] );
280 _tprintf( _T("\n") );
281 ExitProcess( 0 );
283 else if ( 0 == lstrcmpi( argv[argn], TEXT("-?") ) ||
284 0 == lstrcmpi( argv[argn], TEXT("/?") ) ||
285 0 == lstrcmpi( argv[argn], TEXT("-h") ) ||
286 0 == lstrcmpi( argv[argn], TEXT("/h") ) ||
287 0 == lstrcmpi( argv[argn], TEXT("--help") ) )
289 _tprintf(
290 _T("Terminates a process by sending a signal.\n\n")
291 _T("Usage: kill [ -l ] [ -signal ] pid ...\n\n")
292 _T("-l Lists supported signals\n")
293 _T("-signal Sends the specified signal to the given processes.\n")
294 _T(" signal can be a numeric value specifying the signal number\n")
295 _T(" or a string listed by the -l parameter. If no signal is\n")
296 _T(" given SIGTERM (-TERM) is used.\n")
297 _T("pid Process id(s) or executables names(s) of processes to \n")
298 _T(" signal or terminate.\n\n")
300 ExitProcess( 0 );
302 else if ( argv[argn] && ( *argv[argn] == '-' || *argv[argn] == '/' ) )
304 LPCTSTR argsig = CharNext( argv[argn] );
306 int n;
307 for ( n = 0; n < NumSupportedSignals; n++ )
309 _TCHAR *endptr = NULL;
311 if ( 0 == lstrcmpi( SupportedSignals[n].lpSignalName, argsig ) ||
312 _tcstoul( argsig, &endptr, 0 ) == static_cast< unsigned >(SupportedSignals[n].iSignalValue) && (!endptr || !*endptr) )
314 *pSig = SupportedSignals[n].iSignalValue;
315 break;
319 if ( n >= NumSupportedSignals )
321 _ftprintf( stderr,
322 _T("kill: Illegal argument %s\n")
323 _T("Type 'kill --help' to show allowed syntax.\n")
324 _T("Type 'kill -l' to show supported signals.\n"),
325 argv[argn] );
326 ExitProcess( 0 );
329 else
331 unsigned long value = 0;
332 _TCHAR *endptr = NULL;
334 value = _tcstoul( argv[argn], &endptr, 0 );
336 if ( !endptr || !*endptr )
338 if ( *lpdwNumProcesses < dwMaxProcesses )
340 *(lpProcesses++) = value;
341 (*lpdwNumProcesses)++;
344 else
346 HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
348 if ( IsValidHandle( hSnapshot ) )
350 PROCESSENTRY32 pe;
352 pe.dwSize = sizeof(pe);
353 BOOL fSuccess = Process32First( hSnapshot, &pe );
355 while ( fSuccess )
357 if ( 0 == lstrcmpi( argv[argn], pe.szExeFile ) )
359 if ( *lpdwNumProcesses < dwMaxProcesses )
361 *(lpProcesses++) = pe.th32ProcessID;
362 (*lpdwNumProcesses)++;
365 fSuccess = Process32Next( hSnapshot, &pe );
368 CloseHandle( hSnapshot );
374 if ( !*lpdwNumProcesses )
376 _ftprintf( stderr,
377 _T("kill: No process specified.\n")
378 _T("Use kill --help to show allowed syntax.\n")
380 ExitProcess( 0 );
385 void OutputSystemMessage( DWORD dwErrorCode )
387 LPVOID lpMsgBuf;
388 FormatMessageA(
389 FORMAT_MESSAGE_ALLOCATE_BUFFER |
390 FORMAT_MESSAGE_FROM_SYSTEM |
391 FORMAT_MESSAGE_IGNORE_INSERTS,
392 NULL,
393 dwErrorCode,
394 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
395 (LPSTR)&lpMsgBuf,
397 NULL
400 printf( (LPSTR)lpMsgBuf );
401 LocalFree( lpMsgBuf );
404 int _tmain()
406 DWORD dwProcessIds[1024];
407 DWORD nProcesses = elementsof(dwProcessIds);
408 int sig = SIGTERM;
411 ParseCommandArgs( dwProcessIds, &nProcesses, &sig );
413 for ( ULONG n = 0; n < nProcesses; n++ )
415 HANDLE hProcess;
417 _tprintf( _T("Sending signal to process id %d..."), dwProcessIds[n] );
418 hProcess = OpenProcess( PROCESS_TERMINATE | PROCESS_CREATE_THREAD | SYNCHRONIZE |
419 PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,
420 FALSE, dwProcessIds[n] );
422 if ( IsValidHandle( hProcess ) )
424 if ( SIGKILL == sig )
425 TerminateProcess( hProcess, 255 );
426 else
428 if ( RaiseSignalEx( hProcess, sig ) )
429 _tprintf( _T("OK\n") );
430 else
432 OutputSystemMessage( GetLastError() );
436 CloseHandle( hProcess );
438 else
440 OutputSystemMessage( GetLastError() );
444 return 0;