OSDN Git Service

Handling key and mouse events in listctrl is improved
[molby/Molby.git] / wxSources / wxKillAddition.cpp
1 /*
2  *  wxKillAddition.cpp
3  *  Molby
4  *
5  *  Created by Toshi Nagata on 10/04/29.
6  *  Copyright 2010 __MyCompanyName__. All rights reserved.
7  *
8  */
9
10 #if defined(__WXMSW__)
11
12 #include "wx/wxprec.h"
13
14 #ifdef __BORLANDC__
15 #pragma hdrstop
16 #endif
17
18 #include <wx/msw/private.h>     // includes <windows.h>
19
20 #ifndef WX_PRECOMP
21 #include <wx/msw/missing.h>     // CHARSET_HANGUL
22 #include <wx/utils.h>
23 // #include <wx/app.h>
24 #include <wx/intl.h>
25 #include <wx/log.h>
26 #include <wx/timer.h>
27 #endif  //WX_PRECOMP
28
29 #include <wx/msw/registry.h>
30 #include <wx/apptrait.h>
31 #include <wx/dynlib.h>
32 #include <wx/dynload.h>
33 #include <wx/scopeguard.h>
34
35 #include <wx/confbase.h>        // for wxExpandEnvVars()
36
37 #if defined(__CYGWIN__)
38 //CYGWIN gives annoying warning about runtime stuff if we don't do this
39 #   define USE_SYS_TYPES_FD_SET
40 #   include <sys/types.h>
41 #endif
42
43 // Doesn't work with Cygwin at present
44 #if wxUSE_SOCKETS && (defined(__GNUWIN32_OLD__) || defined(__WXWINCE__) || defined(__CYGWIN32__))
45 // apparently we need to include winsock.h to get WSADATA and other stuff
46 // used in wxGetFullHostName() with the old mingw32 versions
47 #include <winsock.h>
48 #endif
49
50 #if !defined(__GNUWIN32__) && !defined(__SALFORDC__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
51 #include <direct.h>
52
53 #ifndef __MWERKS__
54 #include <dos.h>
55 #endif
56 #endif  //GNUWIN32
57
58 #if defined(__CYGWIN__)
59 #include <sys/unistd.h>
60 #include <sys/stat.h>
61 #include <sys/cygwin.h> // for cygwin_conv_to_full_win32_path()
62 #endif  //GNUWIN32
63
64 #ifdef __BORLANDC__ // Please someone tell me which version of Borland needs
65 // this (3.1 I believe) and how to test for it.
66 // If this works for Borland 4.0 as well, then no worries.
67 #include <dir.h>
68 #endif
69
70 // VZ: there is some code using NetXXX() functions to get the full user name:
71 //     I don't think it's a good idea because they don't work under Win95 and
72 //     seem to return the same as wxGetUserId() under NT. If you really want
73 //     to use them, just #define USE_NET_API
74 #undef USE_NET_API
75
76 #ifdef USE_NET_API
77 #include <lm.h>
78 #endif // USE_NET_API
79
80 #if defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
81 #ifndef __UNIX__
82 #include <io.h>
83 #endif
84
85 #ifndef __GNUWIN32__
86 #include <shellapi.h>
87 #endif
88 #endif
89
90 #ifndef __WATCOMC__
91 #if !(defined(_MSC_VER) && (_MSC_VER > 800))
92 #include <errno.h>
93 #endif
94 #endif
95
96 // For wxKillAllChildren
97 #include <tlhelp32.h>
98
99 //  Taken from wxWidgets source, and modified so that recursive killing of
100 //  child processes can be done
101
102 typedef HANDLE (WINAPI *CreateToolhelp32Snapshot_t)(DWORD,DWORD);
103 typedef BOOL (WINAPI *Process32_t)(HANDLE,LPPROCESSENTRY32);
104
105 static CreateToolhelp32Snapshot_t lpfCreateToolhelp32Snapshot;
106 static Process32_t lpfProcess32First, lpfProcess32Next;
107
108 static void InitToolHelp32()
109 {
110     static bool s_initToolHelpDone = false;
111         
112     if (s_initToolHelpDone)
113         return;
114         
115     s_initToolHelpDone = true;
116         
117     lpfCreateToolhelp32Snapshot = NULL;
118     lpfProcess32First = NULL;
119     lpfProcess32Next = NULL;
120         
121 #if wxUSE_DYNLIB_CLASS
122         
123     wxDynamicLibrary dllKernel(_T("kernel32.dll"), wxDL_VERBATIM);
124         
125     // Get procedure addresses.
126     // We are linking to these functions of Kernel32
127     // explicitly, because otherwise a module using
128     // this code would fail to load under Windows NT,
129     // which does not have the Toolhelp32
130     // functions in the Kernel 32.
131     lpfCreateToolhelp32Snapshot =
132         (CreateToolhelp32Snapshot_t)dllKernel.RawGetSymbol(_T("CreateToolhelp32Snapshot"));
133         
134     lpfProcess32First =
135         (Process32_t)dllKernel.RawGetSymbol(_T("Process32First"));
136         
137     lpfProcess32Next =
138         (Process32_t)dllKernel.RawGetSymbol(_T("Process32Next"));
139         
140 #endif // wxUSE_DYNLIB_CLASS
141 }
142
143 typedef struct {
144         long pid;
145         long p_pid;
146         char flag;
147 } sPidListEntry;
148
149 /*  Mark the process with pid and all its children  */
150 static void
151 sMarkProcessAndChildren(long pid, sPidListEntry *myList, int count, long *toKill, int *countToKill)
152 {
153         int i;
154         sPidListEntry *ep;
155         //  Add the process with this pid to the list
156         for (i = 0, ep = myList; i < count; i++, ep++) {
157                 if (ep->flag)
158                         continue;
159                 if (ep->pid == pid && *countToKill < count) {
160                         toKill[*countToKill] = pid;
161                         (*countToKill)++;
162                         ep->flag = 1;
163                         break;
164                 }
165         }
166         //  Look for the child process
167         for (i = 0, ep = myList; i < count; i++, ep++) {
168                 if (ep->flag)
169                         continue;
170                 if (ep->p_pid == pid)
171                         sMarkProcessAndChildren(ep->pid, myList, count, toKill, countToKill);
172         }
173 }
174
175 int 
176 myKillAllChildren(long pid, wxSignal sig, wxKillError *krc)
177 {
178     InitToolHelp32();
179     if (krc)
180         *krc = wxKILL_OK;
181         
182     // If not implemented for this platform (e.g. NT 4.0), silently ignore
183     if (!lpfCreateToolhelp32Snapshot || !lpfProcess32First || !lpfProcess32Next)
184         return 0;
185         
186     // Take a snapshot of all processes in the system.
187     HANDLE hProcessSnap = lpfCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
188     if (hProcessSnap == INVALID_HANDLE_VALUE) {
189         if (krc)
190             *krc = wxKILL_ERROR;
191         return -1;
192     }
193         
194     //Fill in the size of the structure before using it.
195     PROCESSENTRY32 pe;
196     wxZeroMemory(pe);
197     pe.dwSize = sizeof(PROCESSENTRY32);
198         
199     if (!lpfProcess32First(hProcessSnap, &pe)) {
200         // Can't get first process.
201         if (krc)
202             *krc = wxKILL_ERROR;
203         CloseHandle (hProcessSnap);
204         return -1;
205     }
206         
207         //Register the pids and parent pids
208         int count = 4, i = 0;
209         sPidListEntry *myList = (sPidListEntry *)malloc(sizeof(sPidListEntry) * count);
210         if (myList == NULL)
211                 return -1;
212     do {
213                 if (i >= count) {
214                         count += 4;
215                         myList = (sPidListEntry *)realloc(myList, sizeof(sPidListEntry) * count);
216                         if (myList == NULL)
217                                 return -1;
218                 }
219                 myList[i].pid = pe.th32ProcessID;
220                 myList[i].p_pid = pe.th32ParentProcessID;
221                 myList[i].flag = 0;
222                 i++;
223     } while (lpfProcess32Next (hProcessSnap, &pe));
224         CloseHandle (hProcessSnap);
225         count = i;
226         
227         //  Mark the processes to kill
228         long *toKill = (long *)malloc(sizeof(long) * count);
229         i = 0;
230         sMarkProcessAndChildren(pid, myList, count, toKill, &i);
231         count = i;
232         free(myList);
233         
234         //  Kill the processes
235         for (i = 0; i < count; i++) {
236                 if (wxKill(toKill[i], sig, krc))
237                         return -1;
238         }
239         free(toKill);
240         
241     return 0;
242 }
243 #endif