Translated using Weblate (Chinese (Simplified))
[cygwin-setup.git] / processlist.cc
blob4e8518ad048db6079f3e0f8c9f3864baea72b3c0
1 /*
2 * Copyright (c) 2013 Jon TURNEY
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * A copy of the GNU General Public License can be found at
10 * http://www.gnu.org/
14 #include "win32.h"
15 #define PSAPI_VERSION 1
16 #include <psapi.h>
17 #include <stdio.h>
18 #include <stdlib.h>
20 #include "processlist.h"
21 #include <String++.h>
22 #include "LogSingleton.h"
23 #include "script.h"
24 #include "mount.h"
25 #include "filemanip.h"
27 // ---------------------------------------------------------------------------
28 // implements class Process
30 // access to a Windows process
31 // ---------------------------------------------------------------------------
33 Process::Process (DWORD pid) : processID (pid)
37 std::string
38 Process::getName (void)
40 HANDLE hProcess = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
41 char modName[CYG_PATH_MAX];
42 GetModuleFileNameExA (hProcess, NULL, modName, sizeof (modName));
43 CloseHandle (hProcess);
45 std::string s = modName;
46 s += " (pid " + stringify (processID) + ")";
47 return s;
50 DWORD
51 Process::getProcessID (void)
53 return processID;
56 void
57 Process::kill (int force)
59 if (force >= 2)
61 // use TerminateProcess() to request force-killing of the process
62 HANDLE hProcess = OpenProcess (PROCESS_TERMINATE, FALSE, processID);
64 if (hProcess)
66 if (TerminateProcess(hProcess, (UINT)-1))
68 Log (LOG_BABBLE) << "TerminateProcess succeeded on pid " << processID << endLog;
70 else
72 Log (LOG_BABBLE) << "TerminateProcess failed " << GetLastError () << " for pid " << processID << endLog;
74 CloseHandle (hProcess);
77 return;
80 std::string signame;
82 switch (force)
84 case 0:
85 signame = "-TERM";
86 break;
88 default:
89 case 1:
90 signame = "-KILL";
91 break;
94 std::string kill_cmd = backslash (cygpath ("/bin/kill.exe")) + " " + signame + " -W " + stringify (processID);
95 ::run (kill_cmd.c_str ());
99 // test if a module is loaded into a process
101 bool
102 Process::isModuleLoadedInProcess (const WCHAR *moduleName)
104 BOOL match = FALSE;
106 // Get process handle
107 HANDLE hProcess = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
109 if (NULL == hProcess)
110 return FALSE;
112 static unsigned int bytesAllocated = 0;
113 static HMODULE *hMods = 0;
115 // initial allocation
116 if (bytesAllocated == 0)
118 bytesAllocated = sizeof (HMODULE)*1024;
119 hMods = (HMODULE *)malloc (bytesAllocated);
122 while (1)
124 DWORD cbNeeded;
126 // Get a list of all the modules in this process.
127 if (!EnumProcessModules (hProcess, hMods, bytesAllocated, &cbNeeded))
129 // Don't log ERROR_PARTIAL_COPY as expected for System process and those of different bitness
130 if (GetLastError () != ERROR_PARTIAL_COPY)
132 Log (LOG_BABBLE) << "EnumProcessModules failed " << GetLastError () << " for pid " << processID << endLog;
135 cbNeeded = 0;
138 // If we didn't get all modules, retry with a larger array
139 if (cbNeeded > bytesAllocated)
141 bytesAllocated = cbNeeded;
142 hMods = (HMODULE *)realloc (hMods, bytesAllocated);
143 continue;
146 // Search module list for the module we are looking for
147 for (unsigned i = 0; i < (cbNeeded / sizeof (HMODULE)); i++ )
149 WCHAR szModName[CYG_PATH_MAX];
151 // Get the full path to the module's file.
152 if (GetModuleFileNameExW (hProcess, hMods[i], szModName, sizeof (szModName)/sizeof (WCHAR)))
154 WCHAR canonicalModName[CYG_PATH_MAX];
156 // Canonicalise returned module name to long UNC form
157 if (wcscmp (szModName, L"\\\\?\\") != 0)
159 wcscpy (canonicalModName, L"\\\\?\\");
160 wcscat (canonicalModName, szModName);
162 else
164 wcscpy (canonicalModName, szModName);
167 // Does it match the name ?
168 if (wcscmp (moduleName, canonicalModName) == 0)
170 match = TRUE;
171 break;
176 break;
179 // Release the process handle
180 CloseHandle (hProcess);
182 return match;
186 // get a list of currently running processes
188 ProcessList
189 Process::snapshot (void)
191 static DWORD *pProcessIDs = 0;
192 static unsigned int bytesAllocated = 0;
193 DWORD bytesReturned;
195 // initial allocation
196 if (bytesAllocated == 0)
198 bytesAllocated = sizeof (DWORD);
199 pProcessIDs = (DWORD *)malloc (bytesAllocated);
202 // fetch a snapshot of process list
203 while (1)
205 if (!EnumProcesses (pProcessIDs, bytesAllocated, &bytesReturned))
207 Log (LOG_BABBLE) << "EnumProcesses failed " << GetLastError () << endLog;
208 bytesReturned = 0;
211 // If we didn't get all processes, retry with a larger array
212 if (bytesReturned == bytesAllocated)
214 bytesAllocated = bytesAllocated*2;
215 pProcessIDs = (DWORD *)realloc (pProcessIDs, bytesAllocated);
216 continue;
219 break;
222 // convert to ProcessList vector
223 unsigned int nProcesses = bytesReturned/sizeof (DWORD);
224 ProcessList v(nProcesses, 0);
225 for (unsigned int i = 0; i < nProcesses; i++)
227 v[i] = pProcessIDs[i];
230 return v;
234 // list processes which have a given executable module loaded
236 ProcessList
237 Process::listProcessesWithModuleLoaded (const WCHAR *moduleName)
239 ProcessList v;
240 ProcessList pl = snapshot ();
242 for (ProcessList::iterator i = pl.begin (); i != pl.end (); i++)
244 if (i->isModuleLoadedInProcess (moduleName))
246 v.push_back (*i);
250 return v;