Created
August 20, 2014 07:13
-
-
Save CaptainJH/c19a958128c6cea1636d to your computer and use it in GitHub Desktop.
How to use windows named pipe
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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