概述: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);