概述:Windows 管道创建与使用

[toc]

管道类

.h

#pragma once
 
#include <stdio.h>
#include <tchar.h>
 
#include <iostream>
#include <Windows.h>
#include <string>
#include <thread>
#include <memory>
 
#define TIME_ASECOND 1000
 
enum PIPEUSERTYPE {
	USER_CLIENT, //客户端
	USER_SERVER, //服务端
};
 
class PipeIPC {
public:
	explicit PipeIPC(PIPEUSERTYPE role) :m_Role(role), m_hPipeHandle(INVALID_HANDLE_VALUE) {};
	~PipeIPC();
 
	bool WriteData(__in const std::string& datas); //写入数据
	void Release();
	bool ReadData(__out std::string& datas, __out bool bIsPipeEnd); //读取数据
	bool InitPipeIPC(); //初始化管道通信
 
	bool IsInit();
 
	BOOL InitSecurityAttributes();
 
	void Connect();
	void DisConnect();
private:
	PIPEUSERTYPE m_Role;
	HANDLE m_hPipeHandle;
	SECURITY_ATTRIBUTES m_sec_attr;  //security attributes 
};

.cpp

#include "PipeIPC.h"
#include <AccCtrl.h>
#include <AclAPI.h>
 
using namespace std;
 
#define PIPE_SERVER_NAME       "\\\\.\\pipe\\TRustAgent\\pipe.ToFixService"
#define PIPE_CLIENT_NAME       "\\\\.\\pipe\\TrustAgent\\pipe.ToTrustAgent"
 
PipeIPC::~PipeIPC()
{
	if (m_hPipeHandle != INVALID_HANDLE_VALUE)
	{
		DisconnectNamedPipe(m_hPipeHandle);
		CloseHandle(m_hPipeHandle);
	}
}
 
bool PipeIPC::InitPipeIPC()
{
	if (USER_SERVER == m_Role && nullptr != m_hPipeHandle)
	{
		InitSecurityAttributes();
		// cout << "ser" << endl;
		m_hPipeHandle = CreateNamedPipeA(PIPE_SERVER_NAME, PIPE_ACCESS_DUPLEX, //双向模式
			PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE/* | PIPE_NOWAIT*/,
			PIPE_UNLIMITED_INSTANCES,//设置最大容纳实例数目
			0,
			0,
			NULL, (LPSECURITY_ATTRIBUTES)&m_sec_attr);
		//如果管道创建失败
		if (m_hPipeHandle == INVALID_HANDLE_VALUE)
		{
			return false;
		}
 
#if 0
		if (!ConnectNamedPipe(m_hPipeHandle, nullptr)) {
			cout << "ConnectNamedPipe failed" << endl;
			return false;
		}
#endif
	}
	else
	{
		if (WaitNamedPipeA(PIPE_CLIENT_NAME, TIME_ASECOND * 5) == FALSE)
			return 0;
 
		m_hPipeHandle = CreateFileA(
			PIPE_CLIENT_NAME,
			GENERIC_READ | GENERIC_WRITE,
			0,
			NULL,
			OPEN_EXISTING,
			FILE_ATTRIBUTE_NORMAL,
			NULL);
 
		//如果管道创建失败
		if (m_hPipeHandle == INVALID_HANDLE_VALUE)
		{
			return false;
		}
 
		WriteData("[PIPE] ------ V10 Init ------");
	}
 
	return true;
}
 
bool PipeIPC::IsInit()
{
	return m_hPipeHandle == INVALID_HANDLE_VALUE ? false : true;
}
 
/*
	[details] 创建管道去管理员权限
*/
BOOL PipeIPC::InitSecurityAttributes()
{
	PSID pEveryoneSID = NULL;
	PACL pACL = NULL;
	EXPLICIT_ACCESS ea;
	PSECURITY_DESCRIPTOR pSD = NULL;
	void* ea_addr = NULL;
	void* acl_addr = NULL;
	void* sd_addr = NULL;
	SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
 
	if (!AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pEveryoneSID))
	{
		return FALSE;
	}
	ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
	ea.grfAccessPermissions = SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL;
	ea.grfAccessMode = SET_ACCESS;
	ea.grfInheritance = NO_INHERITANCE;
	ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
	ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
	ea.Trustee.ptstrName = (LPTSTR)pEveryoneSID;
	ea_addr = &ea;
	if (ERROR_SUCCESS != SetEntriesInAcl(1, &ea, NULL, &pACL))
	{
		goto cleanup;
	}
	acl_addr = &pACL;
	pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
	if (NULL == pSD)
	{
		goto cleanup;
	}
	if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))
	{
		goto cleanup;
	}
	sd_addr = &pSD;
	if (!SetSecurityDescriptorDacl(pSD, TRUE, pACL, FALSE))
	{
		goto cleanup;
	}
	m_sec_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
	m_sec_attr.lpSecurityDescriptor = pSD;
	m_sec_attr.bInheritHandle = FALSE;
	return TRUE;
 
cleanup:
	if (pEveryoneSID)
		FreeSid(pEveryoneSID);
	if (pACL)
		LocalFree(pACL);
	if (pSD)
		LocalFree(pSD);
	return FALSE;
}
 
void PipeIPC::Connect()
{
	ConnectNamedPipe(m_hPipeHandle, nullptr);
}
 
void PipeIPC::DisConnect()
{
	DisconnectNamedPipe(m_hPipeHandle);
}
 
//读取数据
bool PipeIPC::ReadData(__out std::string& datas, __out bool bIsPipeEnd)
{
	if (INVALID_HANDLE_VALUE == m_hPipeHandle || nullptr == m_hPipeHandle)
	{
		InitPipeIPC();
	}
 
	DWORD cbRead = 0;//定义数据长度
	DWORD cbData = 0;
	if (ReadFile(m_hPipeHandle, &cbData, sizeof(cbData), &cbRead, nullptr) && sizeof(cbData) == cbRead)
	{
		DWORD error = GetLastError();
		bIsPipeEnd = (error == ERROR_BROKEN_PIPE ? true : false);
 
		datas.resize(cbData);
 
		if (ReadFile(m_hPipeHandle, (LPVOID)datas.data(), cbData, &cbRead, nullptr) && cbData == cbRead)
		{
			return true;
		}
	}
	else
	{
		DWORD dwError = GetLastError();
		bIsPipeEnd = (dwError == ERROR_BROKEN_PIPE) ? true : false;
	}
 
	datas.resize(0);
	return false;
}
 
//写入数据
bool PipeIPC::WriteData(__in const std::string& datas)
{
	if (m_Role == USER_SERVER)
	{
		bool connect = ConnectNamedPipe(m_hPipeHandle, NULL);
		if (!connect)
		{
			if (!InitPipeIPC())
			{
				DWORD error = GetLastError();
				if (error != ERROR_PIPE_CONNECTED)
				{
					//cout << "客户端还没连接" << endl;
					//连接失败
					return false;
				}
			}
		}
	}
 
	if (!IsInit())
	{
		if (!InitPipeIPC())
		{
			return false;
		}
	}
 
	//连接成功!
	DWORD wLen;
	const DWORD cbData = datas.size() * sizeof(datas[0]);
 
	if (!WriteFile(m_hPipeHandle, &cbData, sizeof(cbData), &wLen, NULL))
	{
		return false;
	}
	if (!WriteFile(m_hPipeHandle, datas.c_str(), datas.size() * sizeof(datas[0]), &wLen, NULL))
	{
		return false;
	}
 
	return true;
}
 
void PipeIPC::Release()
{
	if (m_hPipeHandle)
	{
		DisconnectNamedPipe(m_hPipeHandle);
		CloseHandle(m_hPipeHandle); // 关闭句柄
		m_hPipeHandle = NULL;
	}
}

定义与声明

__declspec(selectany) PipeIPC* pRead = new PipeIPC(USER_SERVER);
__declspec(selectany) PipeIPC* pWrite = new PipeIPC(USER_CLIENT);

使用

监听管道

随程序同时启动

   
BOOL StartPipeRead()
{
	EventLog(LOG_ALL, "[IPC][THREAD] ,Create PipeReadThread Success, pipe = %p", pRead );
	EventLog(LOG_ALL, "pipe = %p, pipe->IsInit()=%d", pRead, pRead->IsInit());
 
	bool isPipeEnd = true;
	while (true)
	{
		if (isPipeEnd)
		{
			pRead->Connect();
		}
 
		std::string datas;
		if (!pRead->ReadData(datas, isPipeEnd))
		{
			if (isPipeEnd)
			{
				EventLog(LOG_ALL, "-----------[PIPE END]----------");
				pRead->DisConnect();
			}
		}
 
		datas = "Add";
 
		// 数据处理
		if (datas.find("start") != std::string::npos) // 启动成功
		{
			EventLog(LOG_ALL, " [PIPE] [REC] TrustAgentStart");
			// 启动 管道客户端
			if (!StartPipeWrite())
			{
				EventLog(LOG_ALL, " [PIPE] Failed to Create Client Pipe, GetLastError()=", GetLastError());
			}
		}
		else if (!datas.empty())
		{
			EventLog(LOG_ALL, "[PIPE] [RECV] datas: %s", datas.c_str());
			// 调用导出的接口
			{
				std::thread th(HandleFix, datas);
				th.detach();
 
			}
			// NSPTRUST::SendRPCMsgToPlugin(POLICY_SENDTQA_USER, datas.c_str());
		}
	}
}

写管道

启动时机,同名管道的监听管道启动后再启动

BOOL StartPipeWrite()
{
	if (pWrite->IsInit())
		return true;
	else
		return pWrite->InitPipeIPC();
}

写数据

	std::string datas = "Send data to PIPE Read";
	pWrite->WriteData(datas);