C++ 互斥变量清除

有时候,多个程序需要抢占同一个系统资源。例如串口,所以会涉及到程序运行不成功的情况。我的一个初级的解决方案是,杀死前面一个拥有某个互斥变量的程序,启动本程序。下面是一个简单的类,用于清除同名互斥变量。

#pragma once

/* 此类将拥有同名的互斥变量的进程杀死*/
#include <atlstr.h>
#include <functional>
#include <Windows.h>
#include <winternl.h>
#include <vector>
#include <ntstatus.h>
#include <tlhelp32.h>
#include <psapi.h>
#include <iostream>

// NtQueryObject枚举出的内核对象的类型信息的结构
typedef struct _OBJECT_TYPE_INFORMATION
{
	UNICODE_STRING TypeName;
	ULONG TotalNumberOfObjects;
	ULONG TotalNumberOfHandles;
	ULONG TotalPagedPoolUsage;
	ULONG TotalNonPagedPoolUsage;
	ULONG TotalNamePoolUsage;
	ULONG TotalHandleTableUsage;
	ULONG HighWaterNumberOfObjects;
	ULONG HighWaterNumberOfHandles;
	ULONG HighWaterPagedPoolUsage;
	ULONG HighWaterNonPagedPoolUsage;
	ULONG HighWaterNamePoolUsage;
	ULONG HighWaterHandleTableUsage;
	ULONG InvalidAttributes;
	GENERIC_MAPPING GenericMapping;
	ULONG ValidAccessMask;
	BOOLEAN SecurityRequired;
	BOOLEAN MaintainHandleCount;
	ULONG PoolType;
	ULONG DefaultPagedPoolCharge;
	ULONG DefaultNonPagedPoolCharge;
} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
// 一个句柄信息的数据结构
typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO
{
	ULONG ProcessId;
	BYTE ObjectTypeNumber;
	BYTE Flags;
	USHORT Handle;
	PVOID Object;
	ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE_TABLE_ENTRY_INFO, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO;
// 获取一个句柄的详细信息
// 可以获取类型名和内核对象的名字
// bType - 获取句柄的类型名

std::wstring QueryHandleNameInfo(HANDLE handle, BOOL bType)
{
	std::wstring strName;
	const HMODULE hDll = LoadLibrary(_T("ntdll.dll"));
	if (hDll == NULL)
	{
		return strName;
	}
	typedef NTSTATUS(NTAPI *NtQueryObjectFunc)(HANDLE, OBJECT_INFORMATION_CLASS, PVOID, ULONG, PULONG);
	NtQueryObjectFunc NtQueryObject_ = (NtQueryObjectFunc)GetProcAddress(hDll, "NtQueryObject");
	do
	{
		if (NtQueryObject_ == NULL)
		{
			break;
		}
		// 获取信息
		const DWORD ObjectNameInformation = 1;
		OBJECT_INFORMATION_CLASS infoType = bType ? ObjectTypeInformation :
			OBJECT_INFORMATION_CLASS(ObjectNameInformation);
		std::vector<BYTE> objVec(256);
		ULONG bytesOfRead = 0;
		NTSTATUS status = STATUS_UNSUCCESSFUL;
		do
		{
			status = NtQueryObject_(handle, infoType, (void*)objVec.data(), objVec.size(), &bytesOfRead);
			if (STATUS_INFO_LENGTH_MISMATCH == status)
			{
				objVec.resize(objVec.size() * 2);
				continue;
			}
			break;
		} while (TRUE);
		if (!NT_SUCCESS(status))
		{
			break;
		}
		objVec.resize(bytesOfRead);
		if (bType)
		{
			const OBJECT_TYPE_INFORMATION *pObjType =
				reinterpret_cast<OBJECT_TYPE_INFORMATION*>(objVec.data());
			strName = std::wstring(pObjType->TypeName.Buffer, pObjType->TypeName.Length / sizeof(WCHAR));
		}
		else
		{
			const UNICODE_STRING *pObjName = reinterpret_cast<UNICODE_STRING*>(objVec.data());
			strName = std::wstring(pObjName->Buffer, pObjName->Length / sizeof(WCHAR));
		}
	} while (FALSE);
	FreeLibrary(hDll);
	return strName;
}
// 遍历句柄辅助类
class WalkHandleHelper
{
public:
	WalkHandleHelper(const SYSTEM_HANDLE_TABLE_ENTRY_INFO& handleInfo, const HANDLE& handle)
		:m_HandleInfo(handleInfo), m_Handle(handle) {}
	DWORD GetProcessID() const { return m_HandleInfo.ProcessId; }
	std::wstring GetTypeName() const
	{
		return QueryHandleNameInfo(m_Handle, TRUE);
	}
	std::wstring GetObjectName() const
	{
		return QueryHandleNameInfo(m_Handle, FALSE);
	}
private:
	const SYSTEM_HANDLE_TABLE_ENTRY_INFO& m_HandleInfo;
	const HANDLE& m_Handle;
};
// 枚举系统的句柄
void WalkHandle(const std::function<void(const WalkHandleHelper&)> &functor)
{
	const HMODULE hDll = LoadLibrary(_T("ntdll.dll"));
	if (hDll == NULL)
	{
		return;
	}
	// 使用NtQuerySystemInformation检索SystemHandleInformation(16)即可获得系统中所有的句柄信息
	const DWORD SystemHandleInformation = 16;
	// 通过SystemHandleInformation检索到的系统中所有句柄的数据结构
	typedef struct _SYSTEM_HANDLE_INFORMATION
	{
		ULONG HandleCount;
		SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1];
	} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
	typedef NTSTATUS(NTAPI *NtQuerySystemInformationFunc)(ULONG, PVOID, ULONG, PULONG);
	NtQuerySystemInformationFunc NtQuerySystemInformation_ = (NtQuerySystemInformationFunc)
		GetProcAddress(hDll, "NtQuerySystemInformation");
	const HANDLE hCurProcess = GetCurrentProcess();
	do
	{
		if (NULL == NtQuerySystemInformation_)
		{
			break;
		}
		// 获取系统句柄表
		std::vector<BYTE> vecData(512);
		ULONG bytesOfRead = 0;
		NTSTATUS status;
		do
		{
			status = NtQuerySystemInformation_(SystemHandleInformation, vecData.data(), vecData.size(), &bytesOfRead);
			if (STATUS_INFO_LENGTH_MISMATCH == status)
			{
				vecData.resize(vecData.size() * 2);
				continue;
			}
			break;
		} while (TRUE);
		if (!NT_SUCCESS(status))
		{
			break;
		}
		vecData.resize(bytesOfRead);
		PSYSTEM_HANDLE_INFORMATION pSysHandleInfo = (PSYSTEM_HANDLE_INFORMATION)vecData.data();
		for (int i = 0; i < pSysHandleInfo->HandleCount; ++i)
		{
			const HANDLE hOwnProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE,
				pSysHandleInfo->Handles[i].ProcessId);
			if (NULL == hOwnProcess)
			{
				continue;
			}
			HANDLE hDuplicate = NULL;
			// 必须把Handle放入自己的进程中,否则无法获取其他进程拥有Handle的信息
			if (!DuplicateHandle(hOwnProcess, (HANDLE)pSysHandleInfo->Handles[i].Handle, hCurProcess,
				&hDuplicate, 0, 0, DUPLICATE_SAME_ACCESS))
			{
				CloseHandle(hOwnProcess);
				continue;
			}
			WalkHandleHelper helper(pSysHandleInfo->Handles[i], hDuplicate);
			functor(helper);
			CloseHandle(hDuplicate);
			CloseHandle(hOwnProcess);
		}
	} while (FALSE);
	FreeLibrary(hDll);
}
// 枚举进程的互斥量
void EnumProcessMutex(std::wstring MutextName)
{
	std::wcout << _T("Find The Mutex Opened By Current Process:") << std::endl;
	const DWORD dwCurProcess = GetCurrentProcessId();
	WalkHandle([&](const WalkHandleHelper& helper)
	{
		const std::wstring strMutant(L"Mutant");//TestMutex
		if (/*helper.GetProcessID() == dwCurProcess &&*/ helper.GetTypeName().compare(strMutant) == 0)
		{
			WCHAR szExeFile[MAX_PATH] = { 0 };
			HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
			if (hSnap == INVALID_HANDLE_VALUE)
			{
				//cout << "Create Toolhelp false" << endl;
				return;
			}
			PROCESSENTRY32W pEntry32 = { 0 };
			pEntry32.dwSize = sizeof(PROCESSENTRY32W);
			bool bRes = Process32FirstW(hSnap, &pEntry32);
			int pNums = 0;
			while (bRes)
			{
				pNums++;

				//wmemcpy(szExeFile, pEntry32.szExeFile, MAX_PATH);
				//wcout << "PID:" << pEntry32.th32ProcessID << "\t" << "th32ModuleID:" << pEntry32.th32ModuleID << "\t" << "Path:" << pEntry32.szExeFile << endl;
				if (pEntry32.th32ProcessID == helper.GetProcessID())
				{
					wmemcpy(szExeFile, pEntry32.szExeFile, MAX_PATH);//GetModuleFileNameExW((HANDLE)pEntry32.th32ModuleID, NULL, szExeFile, sizeof(szExeFile));
					break;

				}
				bRes = Process32NextW(hSnap, &pEntry32);
			}
			CloseHandle(hSnap);
			//WCHAR szExeFile[MAX_PATH] = { 0 };
			//GetModuleFileNameExW((HANDLE)helper.GetProcessID(), NULL, szExeFile, sizeof(szExeFile));
			if (helper.GetObjectName().find(MutextName) != std::string::npos)
			{
				if (!TerminateProcess((HANDLE)helper.GetProcessID(), 0))
				{
					HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, helper.GetProcessID());
					if (hProcess)
					{
						TerminateProcess(hProcess, 0);
					} 
					else
					{
						CString strKillProcess;
						strKillProcess.Format(_T("cmd.exe /C taskkill /F /pid:%d"), helper.GetProcessID());
						WinExec(CT2A(strKillProcess), SW_HIDE);
						Sleep(1000);
					}
					
				};
				//std::wcout << _T("ProcessID:") << helper.GetProcessID() << _T("ProcessName:")<<   szExeFile << std::endl << _T("ObjectName: ") << helper.GetObjectName().c_str() << std::endl;
			}


		}
	});
}

class CleanMutex
{


public:
	CleanMutex(std::wstring MutextName)
	{
		EnumProcessMutex(MutextName);

	};
	~CleanMutex(void)
	{

	};
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值