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
15 #define PSAPI_VERSION 1
20 #include "processlist.h"
22 #include "LogSingleton.h"
25 #include "filemanip.h"
27 // ---------------------------------------------------------------------------
28 // implements class Process
30 // access to a Windows process
31 // ---------------------------------------------------------------------------
33 Process::Process (DWORD pid
) : processID (pid
)
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
) + ")";
51 Process::getProcessID (void)
57 Process::kill (int force
)
61 // use TerminateProcess() to request force-killing of the process
62 HANDLE hProcess
= OpenProcess (PROCESS_TERMINATE
, FALSE
, processID
);
66 if (TerminateProcess(hProcess
, (UINT
)-1))
68 Log (LOG_BABBLE
) << "TerminateProcess succeeded on pid " << processID
<< endLog
;
72 Log (LOG_BABBLE
) << "TerminateProcess failed " << GetLastError () << " for pid " << processID
<< endLog
;
74 CloseHandle (hProcess
);
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
102 Process::isModuleLoadedInProcess (const WCHAR
*moduleName
)
106 // Get process handle
107 HANDLE hProcess
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
, FALSE
, processID
);
109 if (NULL
== hProcess
)
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
);
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
;
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
);
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
);
164 wcscpy (canonicalModName
, szModName
);
167 // Does it match the name ?
168 if (wcscmp (moduleName
, canonicalModName
) == 0)
179 // Release the process handle
180 CloseHandle (hProcess
);
186 // get a list of currently running processes
189 Process::snapshot (void)
191 static DWORD
*pProcessIDs
= 0;
192 static unsigned int bytesAllocated
= 0;
195 // initial allocation
196 if (bytesAllocated
== 0)
198 bytesAllocated
= sizeof (DWORD
);
199 pProcessIDs
= (DWORD
*)malloc (bytesAllocated
);
202 // fetch a snapshot of process list
205 if (!EnumProcesses (pProcessIDs
, bytesAllocated
, &bytesReturned
))
207 Log (LOG_BABBLE
) << "EnumProcesses failed " << GetLastError () << endLog
;
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
);
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
];
234 // list processes which have a given executable module loaded
237 Process::listProcessesWithModuleLoaded (const WCHAR
*moduleName
)
240 ProcessList pl
= snapshot ();
242 for (ProcessList::iterator i
= pl
.begin (); i
!= pl
.end (); i
++)
244 if (i
->isModuleLoadedInProcess (moduleName
))