|
@@ -188,6 +188,41 @@ DWORD findBrowserProcessByCommandLine(const std::string& executableName, const s
|
|
|
return foundPid;
|
|
|
}
|
|
|
|
|
|
+std::vector<DWORD> findBrowserProcessesByCommandLine(const std::string& executableName, const std::string& uniqueParam) {
|
|
|
+ std::vector<DWORD> pids;
|
|
|
+ HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
|
|
+ if (hSnapshot == INVALID_HANDLE_VALUE) {
|
|
|
+ return pids; // 返回空的向量
|
|
|
+ }
|
|
|
+
|
|
|
+ PROCESSENTRY32 pe32 = { sizeof(pe32) };
|
|
|
+
|
|
|
+ if (Process32First(hSnapshot, &pe32)) {
|
|
|
+ do {
|
|
|
+ // Compare the executable name using a case-insensitive function
|
|
|
+ if (_stricmp(pe32.szExeFile, executableName.c_str()) == 0) {
|
|
|
+ HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pe32.th32ProcessID);
|
|
|
+ if (hProcess) {
|
|
|
+ std::wstring wideCommandLine = GetProcessCommandLine(hProcess);
|
|
|
+ CloseHandle(hProcess);
|
|
|
+
|
|
|
+ // Convert wide string to multi-byte string for comparison
|
|
|
+ // 注意:这个转换可能不安全,取决于宽字符内容。更安全的做法是在宽字符串上直接进行搜索。
|
|
|
+ std::string multiByteCommandLine(wideCommandLine.begin(), wideCommandLine.end());
|
|
|
+
|
|
|
+ // Find the unique parameter in the command line
|
|
|
+ if (multiByteCommandLine.find(uniqueParam) != std::string::npos) {
|
|
|
+ pids.push_back(pe32.th32ProcessID); // 找到匹配,将PID添加到向量中
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } while (Process32Next(hSnapshot, &pe32));
|
|
|
+ }
|
|
|
+
|
|
|
+ CloseHandle(hSnapshot);
|
|
|
+ return pids; // 返回包含所有找到的 PID 的向量
|
|
|
+}
|
|
|
+
|
|
|
HANDLE createAndAssignJobObject(DWORD pid) {
|
|
|
HANDLE hProcess = OpenProcess(PROCESS_SET_QUOTA | PROCESS_TERMINATE, FALSE, pid);
|
|
|
if (hProcess == NULL) {
|
|
@@ -252,23 +287,24 @@ std::tuple<bool, DWORD, HANDLE, HANDLE> startProcessInJob_byLancher(std::string
|
|
|
}
|
|
|
|
|
|
WaitForInputIdle(processInfo.hProcess, INFINITE);
|
|
|
- DWORD mainBrowserPid = 0;
|
|
|
- const int maxAttempts = 10;
|
|
|
- const int retryIntervalMs = 500;
|
|
|
+ const int maxAttempts = 30;
|
|
|
+ const int retryIntervalMs = 100;
|
|
|
+ std::vector<DWORD> processArr;
|
|
|
|
|
|
// Use a robust loop with a short delay to find the main process
|
|
|
+ DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("Searching for the main browser process..., %s, %s", executableName.c_str(), searchParam.c_str());
|
|
|
int i = 0;
|
|
|
do
|
|
|
{
|
|
|
Sleep(retryIntervalMs);
|
|
|
- mainBrowserPid = findBrowserProcessByCommandLine(executableName, searchParam);
|
|
|
- if (mainBrowserPid != 0) {
|
|
|
+ processArr = findBrowserProcessesByCommandLine(executableName, searchParam);
|
|
|
+ if (processArr.size() >= 3)//each browser process has more than 3 subprocesses
|
|
|
+ {
|
|
|
+ DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("Found main browser process: %d", processArr[0]);
|
|
|
break;
|
|
|
}
|
|
|
-
|
|
|
} while (i < maxAttempts);
|
|
|
-
|
|
|
- if (mainBrowserPid == 0) {
|
|
|
+ if (processArr.size() < 3) {
|
|
|
DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("Could not find the main browser process. Terminating launcher...");
|
|
|
TerminateProcess(processInfo.hProcess, 1);
|
|
|
CloseHandle(processInfo.hProcess);
|
|
@@ -276,17 +312,40 @@ std::tuple<bool, DWORD, HANDLE, HANDLE> startProcessInJob_byLancher(std::string
|
|
|
return std::make_tuple(false, 0, (HANDLE)NULL, (HANDLE)NULL);
|
|
|
}
|
|
|
|
|
|
- HANDLE hJob = createAndAssignJobObject(mainBrowserPid);
|
|
|
+ HANDLE hJob = CreateJobObjectA(NULL, NULL);
|
|
|
if (hJob == NULL) {
|
|
|
- CloseHandle(processInfo.hProcess);
|
|
|
- CloseHandle(processInfo.hThread);
|
|
|
+ DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("CreateJobObject failed: %d", GetLastError());
|
|
|
+ return std::make_tuple(false, 0, (HANDLE)NULL, (HANDLE)NULL);
|
|
|
+ }
|
|
|
+
|
|
|
+ JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };
|
|
|
+ jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
|
|
|
+ if (!SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli))) {
|
|
|
+ DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("SetInformationJobObject failed: %d", GetLastError());
|
|
|
+ CloseHandle(hJob);
|
|
|
return std::make_tuple(false, 0, (HANDLE)NULL, (HANDLE)NULL);
|
|
|
}
|
|
|
|
|
|
+ for (auto it : processArr)
|
|
|
+ {
|
|
|
+ HANDLE hProcess = OpenProcess(PROCESS_SET_QUOTA | PROCESS_TERMINATE, FALSE, it);
|
|
|
+ if (hProcess == NULL)
|
|
|
+ continue;
|
|
|
+ if(!AssignProcessToJobObject(hJob, hProcess))
|
|
|
+ {
|
|
|
+ DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("AssignProcessToJobObject failed for PID %d, error: %d", it, GetLastError());
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("AssignProcessToJobObject success for PID %d", it);
|
|
|
+ }
|
|
|
+ CloseHandle(hProcess);
|
|
|
+ }
|
|
|
+
|
|
|
CloseHandle(processInfo.hProcess);
|
|
|
CloseHandle(processInfo.hThread);
|
|
|
|
|
|
- return std::make_tuple(true, mainBrowserPid, hJob, processInfo.hProcess);
|
|
|
+ return std::make_tuple(true, processInfo.dwProcessId, hJob, processInfo.hProcess);
|
|
|
|
|
|
}
|
|
|
|
|
@@ -328,7 +387,7 @@ bool KillProcessById(DWORD pID)
|
|
|
HANDLE Hwnd;
|
|
|
bool ret = false;
|
|
|
Hwnd = OpenProcess(PROCESS_TERMINATE | SYNCHRONIZE, 0, pID);
|
|
|
- if (Hwnd)
|
|
|
+ if (Hwnd)
|
|
|
{
|
|
|
if (TerminateProcess(Hwnd, 0))
|
|
|
{
|