C++ 内存共享/软件守护

2023-11-05

功能描述:在无人看守的情况下,防止软件意外退出。

接口调用简单,只需要简单声明就行:

int main(int argc, char **argv)
{
    QShareProcess shareProcess("共享内存名称随意");

    // 下面实现自己的主体代码即可
    ......
}

类声明:

#if !defined(AFX_SHAREMEMORY_H_INCLUDED)
#define AFX_SHAREMEMORY_H_INCLUDED

class QShareProcess
{
public:
	QShareProcess(const char *name, size_t memsize = 32) ;
	virtual ~QShareProcess();

private:
	int startShared();

	void *getMemPointer();
	
	void write(unsigned long dwData, long lOffset = 0);
	void write(char *pData, long lSize, long lOffset = 0);
	
	void read(char *pData, long lSize, long lOffset = 0);

	void close();
	bool isLive();	
	bool isTerminated();

protected:
	bool createFile(const char *name, size_t size);

	bool mapViewOfFile();
	bool setAllAccess(void* objHandle);
	void freeRes();

	void* m_hToMap;
	void *m_memory;
};

#endif // !defined(AFX_SHAREMEMORY_H_INCLUDED)

类定义:

#include "ShareProcess.h"

#include <Aclapi.h>
#pragma comment(lib,"Advapi32.lib")
QShareProcess::QShareProcess(const char *name, size_t memsize)
	: m_hToMap(0),
	m_memory(0) 
{
	try {
		bool needToInit = createFile(name, memsize);
		mapViewOfFile();
		if (needToInit) {
			memset(m_memory, 0, memsize);
		}
	}
	catch (...) {
		freeRes();
		throw;
	}

	startShared();
}

QShareProcess::~QShareProcess()
{
	freeRes();
}

#include <string>
#include <vector>
#include <thread>
int QShareProcess::startShared()
{
	auto getCurrentModulePath = [] ()-> std::string
	{
		std::vector<char> buffer;
		DWORD size = MAX_PATH;

		while (true) {
			buffer.resize(size + 1);
			DWORD ret = GetModuleFileName(NULL, &buffer[0], size);

			if (ret == 0) {
				return false;
			}
			else if (ret == size || GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
				size += 128;
			}
			else {
				break;
			}
		} // while

		std::string out = &buffer[0];
		return out;
	}; // void

	bool slient = false;
	for (int i = 0; i < __argc; i++) {
		if (_stricmp(__argv[i], "/Slient") == 0) {
			slient = true;
			break;
		}
	} // for

	if (slient) {
		// 互斥 上线地址:端口:服务名
		char	strMutex[100];
		wsprintfA(strMutex, "{4EB9E321-8C12-478F-BC53-9920E7BFE114}");
		HANDLE m_hMutex = CreateMutex(NULL, FALSE, strMutex);
		if (m_hMutex && GetLastError() == ERROR_ALREADY_EXISTS) {
			ReleaseMutex(m_hMutex);
			CloseHandle(m_hMutex);
			ExitProcess(0);
			return 0;
		}

		this->write((DWORD)GetCurrentProcessId(), 12);
		this->write((DWORD)GetTickCount(), 16);

		while (!this->isTerminated()) {
			if (!this->isLive()) {
				TCHAR szCommandline[_MAX_PATH] = { 0 };
				sprintf(szCommandline, "\"%s\"", getCurrentModulePath().c_str());
				for (int i = 1; i < __argc; i++) {
					if (_stricmp(__argv[i], "/Slient") != 0) {
						strcat_s(szCommandline, " ");
						strcat_s(szCommandline, __argv[i]);						
					}
				}
				STARTUPINFO si;
				ZeroMemory(&si, sizeof(STARTUPINFO));
				si.cb = sizeof(STARTUPINFO);
				si.dwFlags = STARTF_USESHOWWINDOW;
				si.wShowWindow = TRUE;

				PROCESS_INFORMATION pi;
				CreateProcess(NULL, (LPTSTR)szCommandline,
					NULL, NULL, FALSE, 0/*CREATE_NEW_CONSOLE*/, NULL, NULL,
					&si, &pi);
			} // if

			this->write((DWORD)GetCurrentProcessId(), 12);
			this->write((DWORD)GetTickCount(), 16);

			std::this_thread::sleep_for(std::chrono::milliseconds(5000));
		}

		ExitProcess(0);
		return 1;
	} // if

	this->write((DWORD)0xABCD);
	this->write((DWORD)GetCurrentProcessId(), 4);
	this->write((DWORD)GetTickCount(), 8);

	TCHAR szCommandline[_MAX_PATH] = { 0 };
	sprintf(szCommandline, "\"%s\" ", getCurrentModulePath().c_str());
	for (int i = 1; i < __argc; i++) {
		if (_stricmp(__argv[i], "/Slient") != 0) {
			strcat_s(szCommandline, " "); 
			strcat_s(szCommandline, __argv[i]);			
		}
	}
	strcat_s(szCommandline, " /Slient");
	STARTUPINFO si;
	ZeroMemory(&si, sizeof(STARTUPINFO));
	si.cb = sizeof(STARTUPINFO);
	si.dwFlags = STARTF_USESHOWWINDOW;
	si.wShowWindow = TRUE;

	PROCESS_INFORMATION pi;
	if (CreateProcess(NULL, (LPTSTR)szCommandline,
		NULL, NULL, FALSE, 0/*CREATE_NEW_CONSOLE*/, NULL, NULL,
		&si, &pi) == 0) {
		return -1;
	}

	return 1;
}

void *QShareProcess::getMemPointer()
{
	return m_memory; 
}

bool QShareProcess::createFile(const char *name, size_t size)
{
	DWORD lowSize = size & 0xffffffff;
	DWORD highSize = (DWORD64)size >> 32 & 0xffffffff;

	//创建共享文件句柄
	m_hToMap = CreateFileMapping(INVALID_HANDLE_VALUE,  //物理文件句柄
		NULL,
		PAGE_READWRITE,        // 可读可写
		highSize,              // 地址偏移:高位
		lowSize,               // 地址偏移:地位
		name);                 // 共享内存名称
	if (m_hToMap == NULL) {
		return false;
	}

	bool needToInit = GetLastError() != ERROR_ALREADY_EXISTS;
	if (needToInit) {
		setAllAccess(m_hToMap);
	}

	return needToInit;
}

#include <stdio.h>
bool QShareProcess::mapViewOfFile()
{
	//映射缓存区视图,得到共享内存的指针
	m_memory = MapViewOfFile(m_hToMap,       //已经创建的文件映射对象的句柄
		FILE_MAP_ALL_ACCESS,	//可读可写
		0,						// 地址偏移:高位
		0,						// 地址偏移:地位
		0);						// 映射视图的大小
	if (m_memory == NULL) {
		return false;
	}

	printf("ShareMemory addr: 0x%08x\n", *(DWORD*)m_memory);

	return true;
}

bool QShareProcess::setAllAccess(void* objHandle)
{
	DWORD errorCode = SetSecurityInfo(objHandle, SE_FILE_OBJECT,
		DACL_SECURITY_INFORMATION,
		NULL,
		NULL,
		NULL,
		NULL);
	if (errorCode != ERROR_SUCCESS) {
		return false;
	}

	return true;
}

void QShareProcess::freeRes()
{
	if (m_memory) {
		UnmapViewOfFile(m_memory);
		m_memory = 0;
	}

	if (m_hToMap) {
		CloseHandle(m_hToMap);
		m_hToMap = 0;
	}
}

void QShareProcess::write(unsigned long dwData, long lOffset)
{
	write((char*)&dwData, sizeof(unsigned long), lOffset);
}

void QShareProcess::write(char *pData, long lSize, long lOffset)
{
	if (m_memory == NULL) 
		return ;

	::memcpy((char*)m_memory + lOffset, pData, lSize);
}

void QShareProcess::read(char *pData, long lSize, long lOffset)
{
	if (m_memory == NULL) 
		return ;

	::memcpy(pData, (char*)m_memory + lOffset, lSize);
}

void QShareProcess::close()
{
	write(0);
}

bool QShareProcess::isTerminated()
{
	DWORD dwValue = 0;
	read((char*)&dwValue, 4);
	if (dwValue = 0xABCD)
		return false;
	else
		return true;
}

#include <TlHelp32.h>
bool QShareProcess::isLive()
{
	DWORD dwProcessID;
	read((char*)&dwProcessID, sizeof(DWORD), 4);

	bool bFind = false;
	HANDLE hSnapShot = INVALID_HANDLE_VALUE;
	PROCESSENTRY32 pe;

	//获取系统快照(hSnapShot)  
	pe.dwSize = sizeof(PROCESSENTRY32);
	hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);

	//查找进程  
	Process32First(hSnapShot, &pe);
	do {
		if (pe.th32ProcessID == dwProcessID) {
			bFind = true;
			break;
		}
	} while (Process32Next(hSnapShot, &pe));

	CloseHandle(hSnapShot);
	return bFind;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 内存共享/软件守护 的相关文章