1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
|
// winpipes.cpp - written and placed in the public domain by Wei Dai
#include "pch.h"
#include "winpipes.h"
#ifdef WINDOWS_PIPES_AVAILABLE
#include "wait.h"
NAMESPACE_BEGIN(CryptoPP)
WindowsHandle::WindowsHandle(HANDLE h, bool own)
: m_h(h), m_own(own)
{
}
WindowsHandle::~WindowsHandle()
{
if (m_own)
{
try
{
CloseHandle();
}
catch (...)
{
}
}
}
bool WindowsHandle::HandleValid() const
{
return m_h && m_h != INVALID_HANDLE_VALUE;
}
void WindowsHandle::AttachHandle(HANDLE h, bool own)
{
if (m_own)
CloseHandle();
m_h = h;
m_own = own;
HandleChanged();
}
HANDLE WindowsHandle::DetachHandle()
{
HANDLE h = m_h;
m_h = INVALID_HANDLE_VALUE;
HandleChanged();
return h;
}
void WindowsHandle::CloseHandle()
{
if (m_h != INVALID_HANDLE_VALUE)
{
::CloseHandle(m_h);
m_h = INVALID_HANDLE_VALUE;
HandleChanged();
}
}
// ********************************************************
void WindowsPipe::HandleError(const char *operation) const
{
DWORD err = GetLastError();
throw Err(GetHandle(), operation, err);
}
WindowsPipe::Err::Err(HANDLE s, const std::string& operation, int error)
: OS_Error(IO_ERROR, "WindowsPipe: " + operation + " operation failed with error 0x" + IntToString(error, 16), operation, error)
, m_h(s)
{
}
// *************************************************************
WindowsPipeReceiver::WindowsPipeReceiver()
: m_resultPending(false), m_eofReceived(false)
{
m_event.AttachHandle(CreateEvent(NULL, true, false, NULL), true);
CheckAndHandleError("CreateEvent", m_event.HandleValid());
memset(&m_overlapped, 0, sizeof(m_overlapped));
m_overlapped.hEvent = m_event;
}
bool WindowsPipeReceiver::Receive(byte* buf, size_t bufLen)
{
assert(!m_resultPending && !m_eofReceived);
HANDLE h = GetHandle();
// don't queue too much at once, or we might use up non-paged memory
if (ReadFile(h, buf, UnsignedMin((DWORD)128*1024, bufLen), &m_lastResult, &m_overlapped))
{
if (m_lastResult == 0)
m_eofReceived = true;
}
else
{
switch (GetLastError())
{
default:
CheckAndHandleError("ReadFile", false);
case ERROR_BROKEN_PIPE:
case ERROR_HANDLE_EOF:
m_lastResult = 0;
m_eofReceived = true;
break;
case ERROR_IO_PENDING:
m_resultPending = true;
}
}
return !m_resultPending;
}
void WindowsPipeReceiver::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
{
if (m_resultPending)
container.AddHandle(m_event, CallStack("WindowsPipeReceiver::GetWaitObjects() - result pending", &callStack));
else if (!m_eofReceived)
container.SetNoWait(CallStack("WindowsPipeReceiver::GetWaitObjects() - result ready", &callStack));
}
unsigned int WindowsPipeReceiver::GetReceiveResult()
{
if (m_resultPending)
{
HANDLE h = GetHandle();
if (GetOverlappedResult(h, &m_overlapped, &m_lastResult, false))
{
if (m_lastResult == 0)
m_eofReceived = true;
}
else
{
switch (GetLastError())
{
default:
CheckAndHandleError("GetOverlappedResult", false);
case ERROR_BROKEN_PIPE:
case ERROR_HANDLE_EOF:
m_lastResult = 0;
m_eofReceived = true;
}
}
m_resultPending = false;
}
return m_lastResult;
}
// *************************************************************
WindowsPipeSender::WindowsPipeSender()
: m_resultPending(false), m_lastResult(0)
{
m_event.AttachHandle(CreateEvent(NULL, true, false, NULL), true);
CheckAndHandleError("CreateEvent", m_event.HandleValid());
memset(&m_overlapped, 0, sizeof(m_overlapped));
m_overlapped.hEvent = m_event;
}
void WindowsPipeSender::Send(const byte* buf, size_t bufLen)
{
DWORD written = 0;
HANDLE h = GetHandle();
// don't queue too much at once, or we might use up non-paged memory
if (WriteFile(h, buf, UnsignedMin((DWORD)128*1024, bufLen), &written, &m_overlapped))
{
m_resultPending = false;
m_lastResult = written;
}
else
{
if (GetLastError() != ERROR_IO_PENDING)
CheckAndHandleError("WriteFile", false);
m_resultPending = true;
}
}
void WindowsPipeSender::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
{
if (m_resultPending)
container.AddHandle(m_event, CallStack("WindowsPipeSender::GetWaitObjects() - result pending", &callStack));
else
container.SetNoWait(CallStack("WindowsPipeSender::GetWaitObjects() - result ready", &callStack));
}
unsigned int WindowsPipeSender::GetSendResult()
{
if (m_resultPending)
{
HANDLE h = GetHandle();
BOOL result = GetOverlappedResult(h, &m_overlapped, &m_lastResult, false);
CheckAndHandleError("GetOverlappedResult", result);
m_resultPending = false;
}
return m_lastResult;
}
NAMESPACE_END
#endif
|