00001
00002
00003
#include "pch.h"
00004
#include "winpipes.h"
00005
00006
#ifdef WINDOWS_PIPES_AVAILABLE
00007
00008
#include "wait.h"
00009
00010 NAMESPACE_BEGIN(CryptoPP)
00011
00012
WindowsHandle::
WindowsHandle(HANDLE h,
bool own)
00013 : m_h(h), m_own(own)
00014 {
00015 }
00016
00017 WindowsHandle::~WindowsHandle()
00018 {
00019
if (m_own)
00020 {
00021
try
00022 {
00023 CloseHandle();
00024 }
00025
catch (...)
00026 {
00027 }
00028 }
00029 }
00030
00031
bool WindowsHandle::HandleValid()
const
00032
{
00033
return m_h && m_h != INVALID_HANDLE_VALUE;
00034 }
00035
00036
void WindowsHandle::AttachHandle(HANDLE h,
bool own)
00037 {
00038
if (m_own)
00039 CloseHandle();
00040
00041 m_h = h;
00042 m_own = own;
00043 HandleChanged();
00044 }
00045
00046 HANDLE WindowsHandle::DetachHandle()
00047 {
00048 HANDLE h = m_h;
00049 m_h = INVALID_HANDLE_VALUE;
00050 HandleChanged();
00051
return h;
00052 }
00053
00054
void WindowsHandle::CloseHandle()
00055 {
00056
if (m_h != INVALID_HANDLE_VALUE)
00057 {
00058 ::CloseHandle(m_h);
00059 m_h = INVALID_HANDLE_VALUE;
00060 HandleChanged();
00061 }
00062 }
00063
00064
00065
00066
void WindowsPipe::HandleError(
const char *operation)
const
00067
{
00068 DWORD err = GetLastError();
00069
throw Err(GetHandle(), operation, err);
00070 }
00071
00072 WindowsPipe::Err::Err(HANDLE s,
const std::string& operation,
int error)
00073 :
OS_Error(IO_ERROR, "
WindowsPipe: " + operation + " operation failed with error 0x" + IntToString(error, 16), operation, error)
00074 , m_h(s)
00075 {
00076 }
00077
00078
00079
00080 WindowsPipeReceiver::WindowsPipeReceiver()
00081 : m_resultPending(false), m_eofReceived(false)
00082 {
00083 m_event.AttachHandle(CreateEvent(NULL,
true,
false, NULL),
true);
00084 CheckAndHandleError(
"CreateEvent", m_event.HandleValid());
00085 memset(&m_overlapped, 0,
sizeof(m_overlapped));
00086 m_overlapped.hEvent = m_event;
00087 }
00088
00089
void WindowsPipeReceiver::Receive(byte* buf,
unsigned int bufLen)
00090 {
00091 assert(!m_resultPending && !m_eofReceived);
00092
00093 HANDLE h = GetHandle();
00094
if (ReadFile(h, buf, bufLen, &m_lastResult, &m_overlapped))
00095 {
00096
if (m_lastResult == 0)
00097 m_eofReceived =
true;
00098 }
00099
else
00100 {
00101
switch (GetLastError())
00102 {
00103
default:
00104 CheckAndHandleError(
"ReadFile",
false);
00105
case ERROR_BROKEN_PIPE:
00106
case ERROR_HANDLE_EOF:
00107 m_lastResult = 0;
00108 m_eofReceived =
true;
00109
break;
00110
case ERROR_IO_PENDING:
00111 m_resultPending =
true;
00112 }
00113 }
00114 }
00115
00116 void WindowsPipeReceiver::GetWaitObjects(
WaitObjectContainer &container)
00117 {
00118
if (m_resultPending)
00119 container.
AddHandle(m_event);
00120
else if (!m_eofReceived)
00121 container.
SetNoWait();
00122 }
00123
00124
unsigned int WindowsPipeReceiver::GetReceiveResult()
00125 {
00126
if (m_resultPending)
00127 {
00128 HANDLE h = GetHandle();
00129
if (GetOverlappedResult(h, &m_overlapped, &m_lastResult,
false))
00130 {
00131
if (m_lastResult == 0)
00132 m_eofReceived =
true;
00133 }
00134
else
00135 {
00136
switch (GetLastError())
00137 {
00138
default:
00139 CheckAndHandleError(
"GetOverlappedResult",
false);
00140
case ERROR_BROKEN_PIPE:
00141
case ERROR_HANDLE_EOF:
00142 m_lastResult = 0;
00143 m_eofReceived =
true;
00144 }
00145 }
00146 m_resultPending =
false;
00147 }
00148
return m_lastResult;
00149 }
00150
00151
00152
00153 WindowsPipeSender::WindowsPipeSender()
00154 : m_resultPending(false), m_lastResult(0)
00155 {
00156 m_event.
AttachHandle(CreateEvent(NULL,
true,
false, NULL),
true);
00157 CheckAndHandleError(
"CreateEvent", m_event.
HandleValid());
00158 memset(&m_overlapped, 0,
sizeof(m_overlapped));
00159 m_overlapped.hEvent = m_event;
00160 }
00161
00162
void WindowsPipeSender::Send(
const byte* buf,
unsigned int bufLen)
00163 {
00164 DWORD written = 0;
00165 HANDLE h = GetHandle();
00166
if (WriteFile(h, buf, bufLen, &written, &m_overlapped))
00167 {
00168 m_resultPending =
false;
00169 m_lastResult = written;
00170 }
00171
else
00172 {
00173
if (GetLastError() != ERROR_IO_PENDING)
00174 CheckAndHandleError(
"WriteFile",
false);
00175
00176 m_resultPending =
true;
00177 }
00178 }
00179
00180 void WindowsPipeSender::GetWaitObjects(
WaitObjectContainer &container)
00181 {
00182
if (m_resultPending)
00183 container.
AddHandle(m_event);
00184
else
00185 container.
SetNoWait();
00186 }
00187
00188
unsigned int WindowsPipeSender::GetSendResult()
00189 {
00190
if (m_resultPending)
00191 {
00192 HANDLE h = GetHandle();
00193 BOOL result = GetOverlappedResult(h, &m_overlapped, &m_lastResult,
false);
00194 CheckAndHandleError(
"GetOverlappedResult", result);
00195 m_resultPending =
false;
00196 }
00197
return m_lastResult;
00198 }
00199
00200 NAMESPACE_END
00201
00202
#endif