xref: /trunk/main/sal/systools/win32/kill/kill.cxx (revision cf6516809c57e1bb0a940545cca99cdad54d4ce2)
187d2adbcSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
387d2adbcSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
487d2adbcSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
587d2adbcSAndrew Rist  * distributed with this work for additional information
687d2adbcSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
787d2adbcSAndrew Rist  * to you under the Apache License, Version 2.0 (the
887d2adbcSAndrew Rist  * "License"); you may not use this file except in compliance
987d2adbcSAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
1187d2adbcSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
1387d2adbcSAndrew Rist  * Unless required by applicable law or agreed to in writing,
1487d2adbcSAndrew Rist  * software distributed under the License is distributed on an
1587d2adbcSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1687d2adbcSAndrew Rist  * KIND, either express or implied.  See the License for the
1787d2adbcSAndrew Rist  * specific language governing permissions and limitations
1887d2adbcSAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
2087d2adbcSAndrew Rist  *************************************************************/
2187d2adbcSAndrew Rist 
2287d2adbcSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sal.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <tchar.h>
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #ifdef _MSC_VER
30cdf0e10cSrcweir #pragma warning(push,1) // disable warnings within system headers
31cdf0e10cSrcweir #endif
32cdf0e10cSrcweir #define WIN32_LEAN_AND_MEAN
33cdf0e10cSrcweir #include <windows.h>
34cdf0e10cSrcweir #include <tlhelp32.h>
35cdf0e10cSrcweir #include <psapi.h>
36cdf0e10cSrcweir #ifdef _MSC_VER
37cdf0e10cSrcweir #pragma warning(pop)
38cdf0e10cSrcweir #endif
39cdf0e10cSrcweir 
40cdf0e10cSrcweir #include <signal.h>
41cdf0e10cSrcweir #include <stdarg.h>
42cdf0e10cSrcweir #include <stdlib.h>
43cdf0e10cSrcweir #include <stdio.h>
44cdf0e10cSrcweir 
45cdf0e10cSrcweir #ifndef SIGNULL
46cdf0e10cSrcweir #define SIGNULL 0
47cdf0e10cSrcweir #endif
48cdf0e10cSrcweir 
49cdf0e10cSrcweir #ifndef SIGKILL
50cdf0e10cSrcweir #define SIGKILL 9
51cdf0e10cSrcweir #endif
52cdf0e10cSrcweir 
53cdf0e10cSrcweir #include <signal.h>
54cdf0e10cSrcweir 
55cdf0e10cSrcweir #define MAX_MODULES 1024
56cdf0e10cSrcweir 
57cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////////
58cdf0e10cSrcweir // Determines if a returned handle value is valid
59cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////////
60cdf0e10cSrcweir 
IsValidHandle(HANDLE handle)61cdf0e10cSrcweir static inline bool IsValidHandle( HANDLE handle )
62cdf0e10cSrcweir {
63cdf0e10cSrcweir     return INVALID_HANDLE_VALUE != handle && NULL != handle;
64cdf0e10cSrcweir }
65cdf0e10cSrcweir 
66cdf0e10cSrcweir 
67cdf0e10cSrcweir #define elementsof( a ) (sizeof(a) / sizeof( (a)[0] ))
68cdf0e10cSrcweir 
69cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////////
7086e1cf34SPedro Giffuni // Retrieves function address in another process
71cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////////
72cdf0e10cSrcweir 
73cdf0e10cSrcweir #if 1
74cdf0e10cSrcweir #define GetProcAddressEx( hProcess, hModule, lpProcName ) GetProcAddress( hModule, lpProcName )
75cdf0e10cSrcweir #else
GetProcAddressEx(HANDLE hProcess,HMODULE hModule,LPCSTR lpProcName)76cdf0e10cSrcweir FARPROC WINAPI GetProcAddressEx( HANDLE hProcess, HMODULE hModule, LPCSTR lpProcName )
77cdf0e10cSrcweir {
78cdf0e10cSrcweir     FARPROC lpfnProcAddress = GetProcAddress( hModule, lpProcName );
79cdf0e10cSrcweir 
80cdf0e10cSrcweir     if ( lpfnProcAddress )
81cdf0e10cSrcweir     {
82cdf0e10cSrcweir         DWORD   dwProcessId = GetProcessId( hProcess );
83cdf0e10cSrcweir 
84cdf0e10cSrcweir         if ( GetCurrentProcessId() != dwProcessId )
85cdf0e10cSrcweir         {
86cdf0e10cSrcweir             FARPROC lpfnRemoteProcAddress = NULL;
87cdf0e10cSrcweir             TCHAR   szBaseName[MAX_PATH];
88cdf0e10cSrcweir 
89cdf0e10cSrcweir             if ( GetModuleBaseName( GetCurrentProcess(), hModule, szBaseName, elementsof(szBaseName) ) )
90cdf0e10cSrcweir             {
91cdf0e10cSrcweir                 HMODULE ahModules[MAX_MODULES];
92cdf0e10cSrcweir                 DWORD   cbNeeded = 0;
93cdf0e10cSrcweir 
94cdf0e10cSrcweir                 if ( EnumProcessModules( hProcess, ahModules, sizeof(ahModules), &cbNeeded ) )
95cdf0e10cSrcweir                 {
96cdf0e10cSrcweir                     ULONG   nModules = cbNeeded / sizeof(ahModules[0]);
97cdf0e10cSrcweir 
98cdf0e10cSrcweir                     for ( ULONG n = 0; n < nModules; n++ )
99cdf0e10cSrcweir                     {
100cdf0e10cSrcweir                         TCHAR   szRemoteBaseName[MAX_PATH];
101cdf0e10cSrcweir 
102cdf0e10cSrcweir                         if ( GetModuleBaseName(
103cdf0e10cSrcweir                             hProcess, ahModules[n], szRemoteBaseName, elementsof(szRemoteBaseName) ) &&
104cdf0e10cSrcweir                             0 == lstrcmpi( szRemoteBaseName, szBaseName )
105cdf0e10cSrcweir                             )
106cdf0e10cSrcweir                         {
107cdf0e10cSrcweir                             lpfnRemoteProcAddress = lpfnProcAddress;
108cdf0e10cSrcweir 
109cdf0e10cSrcweir                             if ( ahModules[n] != hModule )
110cdf0e10cSrcweir                                 *(LPBYTE*)&lpfnRemoteProcAddress += (LPBYTE)ahModules[n] - (LPBYTE)hModule;
111cdf0e10cSrcweir                             break;
112cdf0e10cSrcweir                         }
113cdf0e10cSrcweir                     }
114cdf0e10cSrcweir                 }
115cdf0e10cSrcweir             }
116cdf0e10cSrcweir 
117cdf0e10cSrcweir             lpfnProcAddress = lpfnRemoteProcAddress;
118cdf0e10cSrcweir         }
119cdf0e10cSrcweir     }
120cdf0e10cSrcweir 
121cdf0e10cSrcweir     return lpfnProcAddress;
122cdf0e10cSrcweir }
123cdf0e10cSrcweir #endif
124cdf0e10cSrcweir 
125cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////////
126cdf0e10cSrcweir // Raises a signal in an other process
127cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////////
128cdf0e10cSrcweir 
SignalToExceptionCode(int signal)129cdf0e10cSrcweir static DWORD SignalToExceptionCode( int signal )
130cdf0e10cSrcweir {
131cdf0e10cSrcweir     switch ( signal )
132cdf0e10cSrcweir     {
133cdf0e10cSrcweir     case SIGSEGV:
134cdf0e10cSrcweir         return EXCEPTION_ACCESS_VIOLATION;
135cdf0e10cSrcweir     case SIGFPE:
136cdf0e10cSrcweir         return EXCEPTION_FLT_INVALID_OPERATION;
137cdf0e10cSrcweir     case SIGILL:
138cdf0e10cSrcweir         return EXCEPTION_ILLEGAL_INSTRUCTION;
139cdf0e10cSrcweir     case SIGINT:
140cdf0e10cSrcweir         return CONTROL_C_EXIT;
141cdf0e10cSrcweir     case SIGBREAK:
142cdf0e10cSrcweir         return CONTROL_C_EXIT;
143cdf0e10cSrcweir     default:
144cdf0e10cSrcweir         return 0;
145cdf0e10cSrcweir     }
146cdf0e10cSrcweir }
147cdf0e10cSrcweir 
RaiseSignalEx(HANDLE hProcess,int sig)148cdf0e10cSrcweir static BOOL RaiseSignalEx( HANDLE hProcess, int sig )
149cdf0e10cSrcweir {
150cdf0e10cSrcweir     DWORD   dwProcessId = GetProcessId( hProcess );
151cdf0e10cSrcweir 
152cdf0e10cSrcweir     HANDLE  hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
153cdf0e10cSrcweir     HANDLE  hThread = 0;
154cdf0e10cSrcweir     BOOL fSuccess = FALSE;
155cdf0e10cSrcweir 
156cdf0e10cSrcweir     if ( IsValidHandle(hSnapshot) )
157cdf0e10cSrcweir     {
158cdf0e10cSrcweir         THREADENTRY32   te;
159cdf0e10cSrcweir 
160cdf0e10cSrcweir         te.dwSize = sizeof(te);
161cdf0e10cSrcweir         fSuccess = Thread32First( hSnapshot, &te );
162cdf0e10cSrcweir         while ( fSuccess )
163cdf0e10cSrcweir         {
164cdf0e10cSrcweir             if ( te.th32OwnerProcessID == dwProcessId )
165cdf0e10cSrcweir             {
166cdf0e10cSrcweir                 hThread = OpenThread(
167cdf0e10cSrcweir                     THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION |
168cdf0e10cSrcweir                     THREAD_GET_CONTEXT | THREAD_SET_CONTEXT,
169cdf0e10cSrcweir                     FALSE, te.th32ThreadID );
170cdf0e10cSrcweir                 if ( IsValidHandle(hThread) )
171cdf0e10cSrcweir                     break;
172cdf0e10cSrcweir             }
173cdf0e10cSrcweir 
174cdf0e10cSrcweir             fSuccess = Thread32Next( hSnapshot, &te );
175cdf0e10cSrcweir         }
176cdf0e10cSrcweir 
177cdf0e10cSrcweir         CloseHandle( hSnapshot );
178cdf0e10cSrcweir     }
179cdf0e10cSrcweir 
180cdf0e10cSrcweir     if ( fSuccess )
181cdf0e10cSrcweir     {
182cdf0e10cSrcweir         CONTEXT aContext;
183cdf0e10cSrcweir 
184cdf0e10cSrcweir         if ( SuspendThread( hThread ) != (DWORD)-1 )
185cdf0e10cSrcweir         {
186cdf0e10cSrcweir             ZeroMemory( &aContext, sizeof(aContext) );
187cdf0e10cSrcweir             aContext.ContextFlags = CONTEXT_FULL;
188cdf0e10cSrcweir 
189cdf0e10cSrcweir             fSuccess = GetThreadContext( hThread, &aContext );
190cdf0e10cSrcweir 
191cdf0e10cSrcweir             if ( fSuccess )
192cdf0e10cSrcweir             {
193*e9cec295SDamjan Jovanovic #if defined(INTEL)
194cdf0e10cSrcweir                 if ( sig )
195cdf0e10cSrcweir                 {
196cdf0e10cSrcweir                     DWORD   dwStackBuffer[] =
197cdf0e10cSrcweir                     {
198cdf0e10cSrcweir                         aContext.Eip,
199cdf0e10cSrcweir                         SignalToExceptionCode( sig ),
200cdf0e10cSrcweir                         EXCEPTION_NONCONTINUABLE,
201cdf0e10cSrcweir                         0,
202cdf0e10cSrcweir                         0
203cdf0e10cSrcweir                     };
204cdf0e10cSrcweir 
205cdf0e10cSrcweir                     aContext.Esp -= sizeof(dwStackBuffer);
206cdf0e10cSrcweir                     WriteProcessMemory( hProcess, (LPVOID)aContext.Esp, dwStackBuffer, sizeof(dwStackBuffer), NULL );
207cdf0e10cSrcweir                     aContext.Eip = (DWORD)GetProcAddressEx( hProcess, GetModuleHandleA("KERNEL32"), "RaiseException" );
208cdf0e10cSrcweir                 }
209cdf0e10cSrcweir                 else
210cdf0e10cSrcweir                 {
211*e9cec295SDamjan Jovanovic                     // FIXME: why? Does AMD64 need it too?
212cdf0e10cSrcweir                     aContext.Ecx = aContext.Eax = aContext.Ebx = aContext.Edx = aContext.Esi = aContext.Edi = 0;
213cdf0e10cSrcweir                 }
214*e9cec295SDamjan Jovanovic #elif defined(X86_64)
215*e9cec295SDamjan Jovanovic                 if ( sig )
216*e9cec295SDamjan Jovanovic                 {
217*e9cec295SDamjan Jovanovic                     DWORD   dwStackBuffer[] =
218*e9cec295SDamjan Jovanovic                     {
219*e9cec295SDamjan Jovanovic                         (DWORD)(aContext.Rip >> 32),
220*e9cec295SDamjan Jovanovic                         (DWORD)(aContext.Rip),
221*e9cec295SDamjan Jovanovic                         SignalToExceptionCode( sig ),
222*e9cec295SDamjan Jovanovic                         EXCEPTION_NONCONTINUABLE,
223*e9cec295SDamjan Jovanovic                         0,
224*e9cec295SDamjan Jovanovic                         0,
225*e9cec295SDamjan Jovanovic                         0
226*e9cec295SDamjan Jovanovic                     };
227*e9cec295SDamjan Jovanovic 
228*e9cec295SDamjan Jovanovic                     aContext.Rsp -= sizeof(dwStackBuffer);
229*e9cec295SDamjan Jovanovic                     WriteProcessMemory( hProcess, (LPVOID)aContext.Rsp, dwStackBuffer, sizeof(dwStackBuffer), NULL );
230*e9cec295SDamjan Jovanovic                     aContext.Rip = (DWORD64) GetProcAddressEx( hProcess, GetModuleHandleA("KERNEL32"), "RaiseException" );
231*e9cec295SDamjan Jovanovic                 }
232*e9cec295SDamjan Jovanovic #endif
233cdf0e10cSrcweir 
234cdf0e10cSrcweir                 fSuccess = SetThreadContext( hThread, &aContext );
235cdf0e10cSrcweir             }
236cdf0e10cSrcweir 
237cdf0e10cSrcweir             fSuccess = ResumeThread( hThread ) && fSuccess;
238cdf0e10cSrcweir 
239cdf0e10cSrcweir             DWORD   dwLastError = GetLastError();
240cdf0e10cSrcweir             CloseHandle( hThread );
241cdf0e10cSrcweir             SetLastError( dwLastError );
242cdf0e10cSrcweir 
243cdf0e10cSrcweir             return fSuccess;
244cdf0e10cSrcweir         }
245cdf0e10cSrcweir     }
246cdf0e10cSrcweir 
247cdf0e10cSrcweir     return FALSE;
248cdf0e10cSrcweir }
249cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////////
250cdf0e10cSrcweir // Command line parameter parsing
251cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////////
252cdf0e10cSrcweir 
ParseCommandArgs(LPDWORD lpProcesses,LPDWORD lpdwNumProcesses,int * pSig)253cdf0e10cSrcweir static void ParseCommandArgs( LPDWORD lpProcesses, LPDWORD lpdwNumProcesses, int *pSig )
254cdf0e10cSrcweir {
255cdf0e10cSrcweir     typedef struct _SignalEntry
256cdf0e10cSrcweir     {
257cdf0e10cSrcweir         LPCTSTR lpSignalName;
258cdf0e10cSrcweir         int iSignalValue;
259cdf0e10cSrcweir     } SignalEntry;
260cdf0e10cSrcweir 
261cdf0e10cSrcweir     #define SIG_ENTRY( signal ) { TEXT(#signal), SIG##signal }
262cdf0e10cSrcweir 
263cdf0e10cSrcweir     static SignalEntry SupportedSignals[] =
264cdf0e10cSrcweir     {
265cdf0e10cSrcweir         SIG_ENTRY( NULL ),
266cdf0e10cSrcweir         SIG_ENTRY( SEGV ),
267cdf0e10cSrcweir         SIG_ENTRY( ILL ),
268cdf0e10cSrcweir         SIG_ENTRY( FPE ),
269cdf0e10cSrcweir         SIG_ENTRY( INT ),
270cdf0e10cSrcweir         SIG_ENTRY( BREAK ),
271cdf0e10cSrcweir         SIG_ENTRY( TERM ),
272cdf0e10cSrcweir         SIG_ENTRY( ABRT ),
273cdf0e10cSrcweir         SIG_ENTRY( KILL )
274cdf0e10cSrcweir     };
275cdf0e10cSrcweir 
276cdf0e10cSrcweir     const int NumSupportedSignals = elementsof(SupportedSignals);
277cdf0e10cSrcweir 
278cdf0e10cSrcweir     DWORD   dwMaxProcesses = *lpdwNumProcesses;
279cdf0e10cSrcweir     int     argc = __argc;
280cdf0e10cSrcweir     TCHAR   **argv = __targv;
281cdf0e10cSrcweir 
282cdf0e10cSrcweir     *lpdwNumProcesses = 0;
283cdf0e10cSrcweir 
284cdf0e10cSrcweir     for ( int argn = 1; argn < argc; argn++ )
285cdf0e10cSrcweir     {
286cdf0e10cSrcweir         if ( 0 == lstrcmpi( argv[argn], TEXT("-l") ) ||
287cdf0e10cSrcweir              0 == lstrcmpi( argv[argn], TEXT("/l") ) )
288cdf0e10cSrcweir 
289cdf0e10cSrcweir         {
290cdf0e10cSrcweir             for ( int n = 0; n < NumSupportedSignals; n++ )
291cdf0e10cSrcweir             {
292cdf0e10cSrcweir                 _tprintf( _T("%s "), SupportedSignals[n].lpSignalName );
293cdf0e10cSrcweir             }
294cdf0e10cSrcweir             _tprintf( _T("\n") );
295cdf0e10cSrcweir             ExitProcess( 0 );
296cdf0e10cSrcweir         }
297cdf0e10cSrcweir         else if ( 0 == lstrcmpi( argv[argn], TEXT("-?") ) ||
298cdf0e10cSrcweir                   0 == lstrcmpi( argv[argn], TEXT("/?") ) ||
299cdf0e10cSrcweir                   0 == lstrcmpi( argv[argn], TEXT("-h") ) ||
300cdf0e10cSrcweir                   0 == lstrcmpi( argv[argn], TEXT("/h") ) ||
301cdf0e10cSrcweir                   0 == lstrcmpi( argv[argn], TEXT("--help") ) )
302cdf0e10cSrcweir         {
303cdf0e10cSrcweir             _tprintf(
304cdf0e10cSrcweir                 _T("Terminates a process by sending a signal.\n\n")
305cdf0e10cSrcweir                 _T("Usage: kill [ -l ] [ -signal ] pid ...\n\n")
306cdf0e10cSrcweir                 _T("-l        Lists supported signals\n")
307cdf0e10cSrcweir                 _T("-signal   Sends the specified signal to the given processes.\n")
308cdf0e10cSrcweir                 _T("          signal can be a numeric value specifying the signal number\n")
309cdf0e10cSrcweir                 _T("          or a string listed by the -l parameter. If no signal is\n")
310cdf0e10cSrcweir                 _T("          given SIGTERM (-TERM) is used.\n")
311cdf0e10cSrcweir                 _T("pid       Process id(s) or executables names(s) of processes to \n")
312cdf0e10cSrcweir                 _T("          signal or terminate.\n\n")
313cdf0e10cSrcweir                 );
314cdf0e10cSrcweir             ExitProcess( 0 );
315cdf0e10cSrcweir         }
316cdf0e10cSrcweir         else if ( argv[argn] && ( *argv[argn] == '-' || *argv[argn] == '/' ) )
317cdf0e10cSrcweir         {
318cdf0e10cSrcweir             LPCTSTR argsig = CharNext( argv[argn] );
319cdf0e10cSrcweir 
320cdf0e10cSrcweir             int n;
321cdf0e10cSrcweir             for ( n = 0; n < NumSupportedSignals; n++ )
322cdf0e10cSrcweir             {
323cdf0e10cSrcweir                 _TCHAR *endptr = NULL;
324cdf0e10cSrcweir 
325cdf0e10cSrcweir                 if ( 0 == lstrcmpi( SupportedSignals[n].lpSignalName, argsig ) ||
326cdf0e10cSrcweir                      _tcstoul( argsig, &endptr, 0 ) == static_cast< unsigned >(SupportedSignals[n].iSignalValue) && (!endptr || !*endptr) )
327cdf0e10cSrcweir                 {
328cdf0e10cSrcweir                     *pSig = SupportedSignals[n].iSignalValue;
329cdf0e10cSrcweir                     break;
330cdf0e10cSrcweir                 }
331cdf0e10cSrcweir             }
332cdf0e10cSrcweir 
333cdf0e10cSrcweir             if ( n >= NumSupportedSignals )
334cdf0e10cSrcweir             {
335cdf0e10cSrcweir                 _ftprintf( stderr,
336cdf0e10cSrcweir                     _T("kill: Illegal argument %s\n")
337cdf0e10cSrcweir                     _T("Type 'kill --help' to show allowed syntax.\n")
338cdf0e10cSrcweir                     _T("Type 'kill -l' to show supported signals.\n"),
339cdf0e10cSrcweir                     argv[argn] );
340cdf0e10cSrcweir                 ExitProcess( 0 );
341cdf0e10cSrcweir             }
342cdf0e10cSrcweir         }
343cdf0e10cSrcweir         else
344cdf0e10cSrcweir         {
345cdf0e10cSrcweir             unsigned long value = 0;
346cdf0e10cSrcweir             _TCHAR  *endptr = NULL;
347cdf0e10cSrcweir 
348cdf0e10cSrcweir             value = _tcstoul( argv[argn], &endptr, 0 );
349cdf0e10cSrcweir 
350cdf0e10cSrcweir             if ( !endptr || !*endptr )
351cdf0e10cSrcweir             {
352cdf0e10cSrcweir                 if ( *lpdwNumProcesses < dwMaxProcesses )
353cdf0e10cSrcweir                 {
354cdf0e10cSrcweir                     *(lpProcesses++) = value;
355cdf0e10cSrcweir                     (*lpdwNumProcesses)++;
356cdf0e10cSrcweir                 }
357cdf0e10cSrcweir             }
358cdf0e10cSrcweir             else
359cdf0e10cSrcweir             {
360cdf0e10cSrcweir                 HANDLE  hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
361cdf0e10cSrcweir 
362cdf0e10cSrcweir                 if ( IsValidHandle( hSnapshot ) )
363cdf0e10cSrcweir                 {
364cdf0e10cSrcweir                     PROCESSENTRY32  pe;
365cdf0e10cSrcweir 
366cdf0e10cSrcweir                     pe.dwSize = sizeof(pe);
367cdf0e10cSrcweir                     BOOL fSuccess = Process32First( hSnapshot, &pe );
368cdf0e10cSrcweir 
369cdf0e10cSrcweir                     while ( fSuccess )
370cdf0e10cSrcweir                     {
371cdf0e10cSrcweir                         if ( 0 == lstrcmpi( argv[argn], pe.szExeFile ) )
372cdf0e10cSrcweir                         {
373cdf0e10cSrcweir                             if ( *lpdwNumProcesses < dwMaxProcesses )
374cdf0e10cSrcweir                             {
375cdf0e10cSrcweir                                 *(lpProcesses++) = pe.th32ProcessID;
376cdf0e10cSrcweir                                 (*lpdwNumProcesses)++;
377cdf0e10cSrcweir                             }
378cdf0e10cSrcweir                         }
379cdf0e10cSrcweir                         fSuccess = Process32Next( hSnapshot, &pe );
380cdf0e10cSrcweir                     }
381cdf0e10cSrcweir 
382cdf0e10cSrcweir                     CloseHandle( hSnapshot );
383cdf0e10cSrcweir                 }
384cdf0e10cSrcweir             }
385cdf0e10cSrcweir         }
386cdf0e10cSrcweir     }
387cdf0e10cSrcweir 
388cdf0e10cSrcweir     if ( !*lpdwNumProcesses )
389cdf0e10cSrcweir     {
390cdf0e10cSrcweir         _ftprintf( stderr,
391cdf0e10cSrcweir             _T("kill: No process specified.\n")
392cdf0e10cSrcweir             _T("Use kill --help to show allowed syntax.\n")
393cdf0e10cSrcweir             );
394cdf0e10cSrcweir         ExitProcess( 0 );
395cdf0e10cSrcweir     }
396cdf0e10cSrcweir 
397cdf0e10cSrcweir }
398cdf0e10cSrcweir 
OutputSystemMessage(DWORD dwErrorCode)399cdf0e10cSrcweir void OutputSystemMessage( DWORD dwErrorCode )
400cdf0e10cSrcweir {
401cdf0e10cSrcweir     LPVOID lpMsgBuf;
402cdf0e10cSrcweir     FormatMessageA(
403cdf0e10cSrcweir                     FORMAT_MESSAGE_ALLOCATE_BUFFER |
404cdf0e10cSrcweir                     FORMAT_MESSAGE_FROM_SYSTEM |
405cdf0e10cSrcweir                     FORMAT_MESSAGE_IGNORE_INSERTS,
406cdf0e10cSrcweir                     NULL,
407cdf0e10cSrcweir                     dwErrorCode,
408cdf0e10cSrcweir                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
409cdf0e10cSrcweir                     (LPSTR)&lpMsgBuf,
410cdf0e10cSrcweir                     0,
411cdf0e10cSrcweir                     NULL
412cdf0e10cSrcweir                 );
413cdf0e10cSrcweir 
414cdf0e10cSrcweir     printf( (LPSTR)lpMsgBuf );
415cdf0e10cSrcweir     LocalFree( lpMsgBuf );
416cdf0e10cSrcweir }
417cdf0e10cSrcweir 
_tmain()418cdf0e10cSrcweir int _tmain()
419cdf0e10cSrcweir {
420cdf0e10cSrcweir     DWORD   dwProcessIds[1024];
421cdf0e10cSrcweir     DWORD   nProcesses = elementsof(dwProcessIds);
422cdf0e10cSrcweir     int     sig = SIGTERM;
423cdf0e10cSrcweir 
424cdf0e10cSrcweir 
425cdf0e10cSrcweir     ParseCommandArgs( dwProcessIds, &nProcesses, &sig );
426cdf0e10cSrcweir 
427cdf0e10cSrcweir     for ( ULONG n = 0; n < nProcesses; n++ )
428cdf0e10cSrcweir     {
429cdf0e10cSrcweir         HANDLE  hProcess;
430cdf0e10cSrcweir 
431cdf0e10cSrcweir         _tprintf( _T("Sending signal to process id %d..."), dwProcessIds[n] );
432cdf0e10cSrcweir         hProcess = OpenProcess( PROCESS_TERMINATE | PROCESS_CREATE_THREAD | SYNCHRONIZE |
433cdf0e10cSrcweir             PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,
434cdf0e10cSrcweir             FALSE, dwProcessIds[n] );
435cdf0e10cSrcweir 
436cdf0e10cSrcweir         if ( IsValidHandle( hProcess ) )
437cdf0e10cSrcweir         {
438cdf0e10cSrcweir             if ( SIGKILL == sig )
439cdf0e10cSrcweir                 TerminateProcess( hProcess, 255 );
440cdf0e10cSrcweir             else
441cdf0e10cSrcweir             {
442cdf0e10cSrcweir                 if ( RaiseSignalEx( hProcess, sig ) )
443cdf0e10cSrcweir                     _tprintf( _T("OK\n") );
444cdf0e10cSrcweir                 else
445cdf0e10cSrcweir                 {
446cdf0e10cSrcweir                     OutputSystemMessage( GetLastError() );
447cdf0e10cSrcweir                 }
448cdf0e10cSrcweir             }
449cdf0e10cSrcweir 
450cdf0e10cSrcweir             CloseHandle( hProcess );
451cdf0e10cSrcweir         }
452cdf0e10cSrcweir         else
453cdf0e10cSrcweir         {
454cdf0e10cSrcweir             OutputSystemMessage( GetLastError() );
455cdf0e10cSrcweir         }
456cdf0e10cSrcweir     }
457cdf0e10cSrcweir 
458cdf0e10cSrcweir     return 0;
459cdf0e10cSrcweir }
460