Skip to content

Instantly share code, notes, and snippets.

@CaptainJH
Created August 20, 2014 07:13
Show Gist options
  • Save CaptainJH/c19a958128c6cea1636d to your computer and use it in GitHub Desktop.
Save CaptainJH/c19a958128c6cea1636d to your computer and use it in GitHub Desktop.
How to use windows named pipe
#include <Windows.h>
#include <tlhelp32.h>
#include <psapi.h>
#include <iostream>
#include <utility>
#include <string>
#include <array>
#include <vector>
#include <random>
#include <memory>
#include <assert.h>
#include <functional>
#include <chrono>
#include <thread>
#include <fstream>
#include <limits>
const auto BUFSIZE = 512;
void GetAnswerToRequest(char* pchRequest, char* pchReply, DWORD& bytes)
{
//std::cout << "client request string: " << pchRequest << std::endl;
//strcpy_s(pchReply, BUFSIZE, "Default answer from server");
memset(pchReply, 0, BUFSIZE * sizeof(char));
memset(pchRequest, 0, BUFSIZE * sizeof(char));
std::string temp;
std::getline(std::cin, temp);
strcpy_s(pchReply, BUFSIZE, temp.c_str());
bytes = strlen(pchReply) + 1;
}
std::string GetProcessName(const char* fullPath)
{
std::string temp(fullPath);
auto index = temp.rfind('\\');
return temp.substr(index + 1, temp.length() - index - 1);
}
int CheckParentProcess(const char* processName, std::string& moduleName)
{
int pid = GetCurrentProcessId();
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe = { 0 };
pe.dwSize = sizeof(PROCESSENTRY32);
int ret = -1;
if (Process32First(h, &pe))
{
do {
auto pHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pe.th32ProcessID);
if (pHandle)
{
char name[128];
memset(name, 0, 128 * sizeof(char));
GetModuleFileNameExA(pHandle, 0, name, 128 * sizeof(char));
if (pe.th32ProcessID == pid)
moduleName = name;
auto pName = GetProcessName(name);
if (!strcmp(processName, pName.c_str()) && pe.th32ProcessID != pid)
{
ret = pe.th32ProcessID;
}
}
CloseHandle(pHandle);
} while (Process32Next(h, &pe));
}
CloseHandle(h);
return ret;
}
int CreateChildProcess(const std::string& moduleName)
{
STARTUPINFOA si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
// Start the child process.
if (!CreateProcessA(moduleName.c_str(), // No module name (use command line)
NULL, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi) // Pointer to PROCESS_INFORMATION structure
)
{
return -1;
}
return pi.dwProcessId;
}
int GetPrepared(const char* pipename, int pid, HANDLE& pipeOut)
{
HANDLE hPipe = INVALID_HANDLE_VALUE;
while (1)
{
hPipe = CreateFileA(pipename, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hPipe != INVALID_HANDLE_VALUE)
{
break;
}
if (GetLastError() != ERROR_PIPE_BUSY)
{
return -1;
}
if (!WaitNamedPipeA(pipename, 20000))
{
return -1;
}
}
pipeOut = hPipe;
DWORD dwMode = PIPE_READMODE_MESSAGE;
BOOL fSuccess = SetNamedPipeHandleState(hPipe, &dwMode, NULL, NULL);
if (!fSuccess)
{
return -1;
}
char buf[32];
memset(buf, 0, 32);
sprintf(buf, "READY %d", pid);
DWORD cbWritten = 0;
fSuccess = WriteFile(hPipe, buf, strlen(buf), &cbWritten, NULL);
if (!fSuccess)
{
return -1;
}
return 0;
}
int main()
{
std::string moduleName;
if (CheckParentProcess("Cpp_dojo.exe", moduleName) < 0)
{
char* pipename = "\\\\.\\pipe\\mynamedpipe";
HANDLE hPipe = INVALID_HANDLE_VALUE;
std::vector<std::thread> v_threads;
//auto childID = CreateChildProcess(moduleName);
hPipe = CreateNamedPipeA(pipename, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES,
BUFSIZE, BUFSIZE, 0, NULL);
std::cout << "Pipe server: Main thread awaiting client connection on " << hPipe << std::endl;
if (hPipe == INVALID_HANDLE_VALUE)
{
std::cout << "CreateNamedPipeA failed, GLE=" << GetLastError() << std::endl;
return -1;
}
auto bConnected = ConnectNamedPipe(hPipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
if (bConnected)
{
char* pchRequest = (char*)malloc(BUFSIZE * sizeof(char));
DWORD cbBytesRead = 0, cbReplyBytes = 0, cbWritten = 0;
while (1)
{
memset(pchRequest, 0, BUFSIZ * sizeof(char));
auto fSuccess = ReadFile(hPipe, pchRequest, BUFSIZE * sizeof(char), &cbBytesRead, NULL);
if (!fSuccess || cbBytesRead == 0)
{
if (GetLastError() == ERROR_BROKEN_PIPE)
{
std::cout << "InstanceThread: client disconnected." << std::endl;
}
else
{
std::cout << "InstanceThread ReadFile failed, GLE=" << GetLastError() << std::endl;
}
break;
}
std::cout << pchRequest << std::endl;
}
FlushFileBuffers(hPipe);
DisconnectNamedPipe(hPipe);
CloseHandle(hPipe);
free(pchRequest);
}
else
{
CloseHandle(hPipe);
}
}
else
{
char* pipename = "\\\\.\\pipe\\mynamedpipe";
HANDLE hPipe = INVALID_HANDLE_VALUE;
std::vector<std::thread> v_threads;
GetPrepared(pipename, GetCurrentProcessId(), hPipe);
char* pchRequest = (char*)malloc(BUFSIZE * sizeof(char));
char* pchReply = (char*)malloc(BUFSIZE * sizeof(char));
DWORD cbBytesRead = 0, cbReplyBytes = 0, cbWritten = 0;
while (1)
{
memset(pchReply, 0, BUFSIZ * sizeof(char));
GetAnswerToRequest(pchRequest, pchReply, cbReplyBytes);
if (!strcmp(pchReply, "exit"))
break;
auto fSuccess = WriteFile(hPipe, pchReply, cbReplyBytes, &cbWritten, NULL);
if (!fSuccess || cbReplyBytes != cbWritten)
{
std::cout << "InstanceThread WriteFile failed, GLE=" << GetLastError() << std::endl;
break;
}
}
FlushFileBuffers(hPipe);
DisconnectNamedPipe(hPipe);
CloseHandle(hPipe);
free(pchRequest);
free(pchReply);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment