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