#include "HGNamedPipe.h" #include "HGInc.h" #include "HGThread.h" #include struct HGNamedPipeServerImpl { HGNamedPipeServerImpl() { #if defined(HG_CMP_MSC) m_hConnectEvent = NULL; m_hWriteEvent = NULL; m_hReadEvent = NULL; m_hProcessEvent = NULL; m_hPipe = INVALID_HANDLE_VALUE; m_clientPid = 0; m_thread = NULL; m_error = HGFALSE; m_break = HGFALSE; #else // TODO #endif } ~HGNamedPipeServerImpl() { #if defined(HG_CMP_MSC) HGBase_CloseThread(m_thread); m_thread = NULL; CloseHandle(m_hPipe); m_hPipe = INVALID_HANDLE_VALUE; CloseHandle(m_hProcessEvent); m_hProcessEvent = NULL; CloseHandle(m_hReadEvent); m_hReadEvent = NULL; CloseHandle(m_hWriteEvent); m_hWriteEvent = NULL; CloseHandle(m_hConnectEvent); m_hConnectEvent = NULL; #else // TODO #endif } #if defined(HG_CMP_MSC) HANDLE m_hConnectEvent; HANDLE m_hWriteEvent; HANDLE m_hReadEvent; HANDLE m_hProcessEvent; HANDLE m_hPipe; DWORD m_clientPid; HGThread m_thread; HGBool m_error; HGBool m_break; #else // TODO #endif }; struct HGNamedPipeClientImpl { HGNamedPipeClientImpl() { #if defined(HG_CMP_MSC) m_hWriteEvent = NULL; m_hReadEvent = NULL; m_hProcessEvent = NULL; m_hPipe = INVALID_HANDLE_VALUE; m_serverPid = 0; m_thread = NULL; m_error = HGFALSE; m_break = HGFALSE; #else // TODO #endif } ~HGNamedPipeClientImpl() { #if defined(HG_CMP_MSC) HGBase_CloseThread(m_thread); m_thread = NULL; CloseHandle(m_hPipe); m_hPipe = INVALID_HANDLE_VALUE; CloseHandle(m_hProcessEvent); m_hProcessEvent = NULL; CloseHandle(m_hReadEvent); m_hReadEvent = NULL; CloseHandle(m_hWriteEvent); m_hWriteEvent = NULL; #else // TODO #endif } #if defined(HG_CMP_MSC) HANDLE m_hWriteEvent; HANDLE m_hReadEvent; HANDLE m_hProcessEvent; HANDLE m_hPipe; DWORD m_serverPid; HGThread m_thread; HGBool m_error; HGBool m_break; #else // TODO #endif }; static void HGAPI NamedPipeServerFunc(HGThread thread, HGPointer param) { HGNamedPipeServerImpl* p = (HGNamedPipeServerImpl*)param; #if defined(HG_CMP_MSC) HANDLE handles[2]; handles[0] = OpenProcess(SYNCHRONIZE, FALSE, p->m_clientPid); handles[1] = p->m_hProcessEvent; if (WAIT_OBJECT_0 == WaitForMultipleObjects(2, handles, FALSE, INFINITE)) { p->m_error = HGTRUE; SetEvent(p->m_hWriteEvent); SetEvent(p->m_hReadEvent); } CloseHandle(handles[0]); #else // TODO #endif } static void NamedPipeClientFunc(HGThread thread, HGPointer param) { HGNamedPipeClientImpl* p = (HGNamedPipeClientImpl*)param; #if defined(HG_CMP_MSC) HANDLE handles[2]; handles[0] = OpenProcess(SYNCHRONIZE, FALSE, p->m_serverPid); handles[1] = p->m_hProcessEvent; if (WAIT_OBJECT_0 == WaitForMultipleObjects(2, handles, FALSE, INFINITE)) { p->m_error = HGTRUE; SetEvent(p->m_hWriteEvent); SetEvent(p->m_hReadEvent); } CloseHandle(handles[0]); #else // TODO #endif } HGResult HGAPI HGBase_OpenNamedPipeServer(const HGChar* pipeName, HGNamedPipeServer* server) { if (NULL == pipeName || NULL == server) { return HGBASE_ERR_INVALIDARG; } #if defined(HG_CMP_MSC) HANDLE hConnectEvent = CreateEventA(NULL, TRUE, FALSE, NULL); assert(NULL != hConnectEvent); HANDLE hWriteEvent = CreateEventA(NULL, TRUE, FALSE, NULL); assert(NULL != hWriteEvent); HANDLE hReadEvent = CreateEventA(NULL, TRUE, FALSE, NULL); assert(NULL != hReadEvent); HANDLE hProcessEvent = CreateEventA(NULL, TRUE, FALSE, NULL); assert(NULL != hProcessEvent); char name[256]; sprintf(name, "\\\\.\\pipe\\%s", pipeName); HANDLE hPipe = CreateNamedPipeA(name, PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED, 0, 1, 1024, 1024, 0, NULL); if (INVALID_HANDLE_VALUE == hPipe) { CloseHandle(hProcessEvent); CloseHandle(hReadEvent); CloseHandle(hWriteEvent); CloseHandle(hConnectEvent); return HGBASE_ERR_FAIL; } HGNamedPipeServerImpl* pipeServerImpl = new HGNamedPipeServerImpl; pipeServerImpl->m_hConnectEvent = hConnectEvent; pipeServerImpl->m_hWriteEvent = hWriteEvent; pipeServerImpl->m_hReadEvent = hReadEvent; pipeServerImpl->m_hProcessEvent = hProcessEvent; pipeServerImpl->m_hPipe = hPipe; *server = (HGNamedPipeServer)pipeServerImpl; #else // TODO #endif return HGBASE_ERR_OK; } HGResult HGAPI HGBase_CloseNamedPipeServer(HGNamedPipeServer server) { if (NULL == server) { return HGBASE_ERR_INVALIDARG; } HGNamedPipeServerImpl* pipeServerImpl = (HGNamedPipeServerImpl*)server; delete pipeServerImpl; return HGBASE_ERR_OK; } HGResult HGAPI HGBase_NamedPipeServerWrite(HGNamedPipeServer server, const HGByte* data, HGUInt size, HGUInt* writeSize) { if (NULL == server || NULL == data || 0 == size) { return HGBASE_ERR_INVALIDARG; } HGNamedPipeServerImpl* pipeServerImpl = (HGNamedPipeServerImpl*)server; #if defined(HG_CMP_MSC) if (NULL == pipeServerImpl->m_thread || pipeServerImpl->m_error || pipeServerImpl->m_break) { return HGBASE_ERR_FAIL; } OVERLAPPED overlapped = { 0 }; overlapped.hEvent = pipeServerImpl->m_hWriteEvent; DWORD dwNumerOfWriteBytes = 0; if (!WriteFile(pipeServerImpl->m_hPipe, data, size, &dwNumerOfWriteBytes, &overlapped)) { if (ERROR_IO_PENDING != GetLastError()) { // 写入错误 return HGBASE_ERR_FAIL; } WaitForSingleObject(pipeServerImpl->m_hWriteEvent, INFINITE); if (!GetOverlappedResult(pipeServerImpl->m_hPipe, &overlapped, &dwNumerOfWriteBytes, TRUE)) { // 手动停止 return HGBASE_ERR_FAIL; } } if (NULL != writeSize) *writeSize = dwNumerOfWriteBytes; #else // TODO #endif return HGBASE_ERR_OK; } HGResult HGAPI HGBase_NamedPipeServerRead(HGNamedPipeServer server, HGByte* data, HGUInt size, HGUInt* readSize) { if (NULL == server || NULL == data || 0 == size) { return HGBASE_ERR_INVALIDARG; } HGNamedPipeServerImpl* pipeServerImpl = (HGNamedPipeServerImpl*)server; #if defined(HG_CMP_MSC) if (NULL == pipeServerImpl->m_thread) // 未连接 { OVERLAPPED overlapped = { 0 }; overlapped.hEvent = pipeServerImpl->m_hConnectEvent; if (!ConnectNamedPipe(pipeServerImpl->m_hPipe, &overlapped)) { DWORD err = GetLastError(); if (ERROR_IO_PENDING != err && ERROR_PIPE_CONNECTED != err) { // 等待连接出错 return HGBASE_ERR_FAIL; } if (ERROR_IO_PENDING == err) { // 等待连接 WaitForSingleObject(pipeServerImpl->m_hConnectEvent, INFINITE); DWORD dwTransferBytes = 0; // 此值无意义 if (!GetOverlappedResult(pipeServerImpl->m_hPipe, &overlapped, &dwTransferBytes, TRUE)) { // 手动停止 return HGBASE_ERR_FAIL; } } } // 读取对方进程ID memset(&overlapped, 0, sizeof(OVERLAPPED)); overlapped.hEvent = pipeServerImpl->m_hReadEvent; DWORD dwNumerOfReadBytes = 0; DWORD clientPid = 0; if (!ReadFile(pipeServerImpl->m_hPipe, &clientPid, sizeof(DWORD), &dwNumerOfReadBytes, &overlapped)) { if (ERROR_IO_PENDING != GetLastError()) { // 读取错误 return HGBASE_ERR_FAIL; } WaitForSingleObject(pipeServerImpl->m_hReadEvent, INFINITE); if (!GetOverlappedResult(pipeServerImpl->m_hPipe, &overlapped, &dwNumerOfReadBytes, TRUE)) { // 手动停止 return HGBASE_ERR_FAIL; } } if (sizeof(DWORD) != dwNumerOfReadBytes || 0 == clientPid) { return HGBASE_ERR_FAIL; } // 发送己方进程ID memset(&overlapped, 0, sizeof(OVERLAPPED)); overlapped.hEvent = pipeServerImpl->m_hWriteEvent; DWORD dwNumerOfWriteBytes = 0; DWORD serverPid = GetCurrentProcessId(); if (!WriteFile(pipeServerImpl->m_hPipe, &serverPid, sizeof(DWORD), &dwNumerOfWriteBytes, &overlapped)) { if (ERROR_IO_PENDING != GetLastError()) { // 写入错误 return HGBASE_ERR_FAIL; } WaitForSingleObject(pipeServerImpl->m_hWriteEvent, INFINITE); if (!GetOverlappedResult(pipeServerImpl->m_hPipe, &overlapped, &dwNumerOfWriteBytes, TRUE)) { // 手动停止 return HGBASE_ERR_FAIL; } } if (sizeof(DWORD) != dwNumerOfWriteBytes) { return HGBASE_ERR_FAIL; } // 创建线程等待对方进程ID pipeServerImpl->m_clientPid = clientPid; HGBase_OpenThread(NamedPipeServerFunc, pipeServerImpl, &pipeServerImpl->m_thread); assert(NULL != pipeServerImpl->m_thread); } if (pipeServerImpl->m_error || pipeServerImpl->m_break) { return HGBASE_ERR_FAIL; } OVERLAPPED overlapped = { 0 }; overlapped.hEvent = pipeServerImpl->m_hReadEvent; DWORD dwNumerOfReadBytes = 0; if (!ReadFile(pipeServerImpl->m_hPipe, data, size, &dwNumerOfReadBytes, &overlapped)) { if (ERROR_IO_PENDING != GetLastError()) { // 读取错误 return HGBASE_ERR_FAIL; } WaitForSingleObject(pipeServerImpl->m_hReadEvent, INFINITE); if (!GetOverlappedResult(pipeServerImpl->m_hPipe, &overlapped, &dwNumerOfReadBytes, TRUE)) { // 手动停止 return HGBASE_ERR_FAIL; } } if (NULL != readSize) *readSize = dwNumerOfReadBytes; #else // TODO #endif return HGBASE_ERR_OK; } HGResult HGAPI HGBase_NamedPipeServerStop(HGNamedPipeServer server) { if (NULL == server) { return HGBASE_ERR_INVALIDARG; } HGNamedPipeServerImpl* pipeServerImpl = (HGNamedPipeServerImpl*)server; #if defined(HG_CMP_MSC) pipeServerImpl->m_break = HGTRUE; SetEvent(pipeServerImpl->m_hConnectEvent); SetEvent(pipeServerImpl->m_hWriteEvent); SetEvent(pipeServerImpl->m_hReadEvent); SetEvent(pipeServerImpl->m_hProcessEvent); #else // TODO #endif return HGBASE_ERR_OK; } HGResult HGAPI HGBase_OpenNamedPipeClient(const HGChar* pipeName, HGNamedPipeClient* client) { if (NULL == pipeName || NULL == client) { return HGBASE_ERR_INVALIDARG; } #if defined(HG_CMP_MSC) HANDLE hWriteEvent = CreateEventA(NULL, TRUE, FALSE, NULL); assert(NULL != hWriteEvent); HANDLE hReadEvent = CreateEventA(NULL, TRUE, FALSE, NULL); assert(NULL != hReadEvent); HANDLE hProcessEvent = CreateEventA(NULL, TRUE, FALSE, NULL); assert(NULL != hProcessEvent); char name[256]; sprintf(name, "\\\\.\\pipe\\%s", pipeName); HANDLE hPipe = CreateFileA(name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); if (INVALID_HANDLE_VALUE == hPipe) { CloseHandle(hProcessEvent); CloseHandle(hReadEvent); CloseHandle(hWriteEvent); return HGBASE_ERR_FAIL; } // 发送己方进程ID OVERLAPPED overlapped = { 0 }; overlapped.hEvent = hWriteEvent; DWORD dwNumerOfWriteBytes = 0; DWORD clientPid = GetCurrentProcessId(); if (!WriteFile(hPipe, &clientPid, sizeof(DWORD), &dwNumerOfWriteBytes, &overlapped)) { if (ERROR_IO_PENDING != GetLastError()) { // 写入错误 CloseHandle(hPipe); CloseHandle(hProcessEvent); CloseHandle(hReadEvent); CloseHandle(hWriteEvent); return HGBASE_ERR_FAIL; } WaitForSingleObject(hWriteEvent, INFINITE); if (!GetOverlappedResult(hPipe, &overlapped, &dwNumerOfWriteBytes, TRUE)) { // 手动停止 CloseHandle(hPipe); CloseHandle(hProcessEvent); CloseHandle(hReadEvent); CloseHandle(hWriteEvent); return HGBASE_ERR_FAIL; } } if (sizeof(DWORD) != dwNumerOfWriteBytes) { CloseHandle(hPipe); CloseHandle(hProcessEvent); CloseHandle(hReadEvent); CloseHandle(hWriteEvent); return HGBASE_ERR_FAIL; } // 读取对方进程ID memset(&overlapped, 0, sizeof(OVERLAPPED)); overlapped.hEvent = hReadEvent; DWORD dwNumerOfReadBytes = 0; DWORD serverPid = 0; if (!ReadFile(hPipe, &serverPid, sizeof(DWORD), &dwNumerOfReadBytes, &overlapped)) { if (ERROR_IO_PENDING != GetLastError()) { // 读取错误 CloseHandle(hPipe); CloseHandle(hProcessEvent); CloseHandle(hReadEvent); CloseHandle(hWriteEvent); return HGBASE_ERR_FAIL; } WaitForSingleObject(hReadEvent, INFINITE); if (!GetOverlappedResult(hPipe, &overlapped, &dwNumerOfReadBytes, TRUE)) { // 手动停止 CloseHandle(hPipe); CloseHandle(hProcessEvent); CloseHandle(hReadEvent); CloseHandle(hWriteEvent); return HGBASE_ERR_FAIL; } } if (sizeof(DWORD) != dwNumerOfReadBytes || 0 == serverPid) { CloseHandle(hPipe); CloseHandle(hProcessEvent); CloseHandle(hReadEvent); CloseHandle(hWriteEvent); return HGBASE_ERR_FAIL; } // 创建线程等待对方进程ID HGNamedPipeClientImpl* pipeClientImpl = new HGNamedPipeClientImpl; pipeClientImpl->m_hWriteEvent = hWriteEvent; pipeClientImpl->m_hReadEvent = hReadEvent; pipeClientImpl->m_hProcessEvent = hProcessEvent; pipeClientImpl->m_hPipe = hPipe; pipeClientImpl->m_serverPid = serverPid; HGBase_OpenThread(NamedPipeServerFunc, pipeClientImpl, &pipeClientImpl->m_thread); assert(NULL != pipeClientImpl->m_thread); *client = (HGNamedPipeClient)pipeClientImpl; #else // TODO #endif return HGBASE_ERR_OK; } HGResult HGAPI HGBase_CloseNamedPipeClient(HGNamedPipeClient client) { if (NULL == client) { return HGBASE_ERR_INVALIDARG; } HGNamedPipeClientImpl* pipeClientImpl = (HGNamedPipeClientImpl*)client; delete pipeClientImpl; return HGBASE_ERR_OK; } HGResult HGAPI HGBase_NamedPipeClientWrite(HGNamedPipeClient client, const HGByte* data, HGUInt size, HGUInt* writeSize) { if (NULL == client) { return HGBASE_ERR_INVALIDARG; } HGNamedPipeClientImpl* pipeClientImpl = (HGNamedPipeClientImpl*)client; #if defined(HG_CMP_MSC) assert(NULL != pipeClientImpl->m_thread); if (pipeClientImpl->m_error || pipeClientImpl->m_break) { return HGBASE_ERR_FAIL; } OVERLAPPED overlapped = { 0 }; overlapped.hEvent = pipeClientImpl->m_hWriteEvent; DWORD dwNumerOfWriteBytes = 0; if (!WriteFile(pipeClientImpl->m_hPipe, data, size, &dwNumerOfWriteBytes, &overlapped)) { if (ERROR_IO_PENDING != GetLastError()) { // 写入错误 return HGBASE_ERR_FAIL; } WaitForSingleObject(pipeClientImpl->m_hWriteEvent, INFINITE); if (!GetOverlappedResult(pipeClientImpl->m_hPipe, &overlapped, &dwNumerOfWriteBytes, TRUE)) { // 手动停止 return HGBASE_ERR_FAIL; } } if (NULL != writeSize) *writeSize = dwNumerOfWriteBytes; #else // TODO #endif return HGBASE_ERR_OK; } HGResult HGAPI HGBase_NamedPipeClientRead(HGNamedPipeClient client, HGByte* data, HGUInt size, HGUInt* readSize) { if (NULL == client) { return HGBASE_ERR_INVALIDARG; } HGNamedPipeClientImpl* pipeClientImpl = (HGNamedPipeClientImpl*)client; #if defined(HG_CMP_MSC) assert(NULL != pipeClientImpl->m_thread); if (pipeClientImpl->m_error || pipeClientImpl->m_break) { return HGBASE_ERR_FAIL; } OVERLAPPED overlapped = { 0 }; overlapped.hEvent = pipeClientImpl->m_hReadEvent; DWORD dwNumerOfReadBytes = 0; if (!ReadFile(pipeClientImpl->m_hPipe, data, size, &dwNumerOfReadBytes, &overlapped)) { if (ERROR_IO_PENDING != GetLastError()) { // 读取错误 return HGBASE_ERR_FAIL; } WaitForSingleObject(pipeClientImpl->m_hReadEvent, INFINITE); if (!GetOverlappedResult(pipeClientImpl->m_hPipe, &overlapped, &dwNumerOfReadBytes, TRUE)) { // 手动停止 return HGBASE_ERR_FAIL; } } if (NULL != readSize) *readSize = dwNumerOfReadBytes; #else // TODO #endif return HGBASE_ERR_OK; } HGResult HGAPI HGBase_NamedPipeClientStop(HGNamedPipeClient client) { if (NULL == client) { return HGBASE_ERR_INVALIDARG; } HGNamedPipeClientImpl* pipeClientImpl = (HGNamedPipeClientImpl*)client; #if defined(HG_CMP_MSC) pipeClientImpl->m_break = HGTRUE; SetEvent(pipeClientImpl->m_hWriteEvent); SetEvent(pipeClientImpl->m_hReadEvent); SetEvent(pipeClientImpl->m_hProcessEvent); #else // TODO #endif return HGBASE_ERR_OK; }