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 bool WindowsPipeReceiver::Receive(byte* buf, size_t bufLen)
00090 {
00091 assert(!m_resultPending && !m_eofReceived);
00092
00093 HANDLE h = GetHandle();
00094
00095 if (ReadFile(h, buf, UnsignedMin((DWORD)128*1024, bufLen), &m_lastResult, &m_overlapped))
00096 {
00097 if (m_lastResult == 0)
00098 m_eofReceived = true;
00099 }
00100 else
00101 {
00102 switch (GetLastError())
00103 {
00104 default:
00105 CheckAndHandleError("ReadFile", false);
00106 case ERROR_BROKEN_PIPE:
00107 case ERROR_HANDLE_EOF:
00108 m_lastResult = 0;
00109 m_eofReceived = true;
00110 break;
00111 case ERROR_IO_PENDING:
00112 m_resultPending = true;
00113 }
00114 }
00115 return !m_resultPending;
00116 }
00117
00118 void WindowsPipeReceiver::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
00119 {
00120 if (m_resultPending)
00121 container.AddHandle(m_event, CallStack("WindowsPipeReceiver::GetWaitObjects() - result pending", &callStack));
00122 else if (!m_eofReceived)
00123 container.SetNoWait(CallStack("WindowsPipeReceiver::GetWaitObjects() - result ready", &callStack));
00124 }
00125
00126 unsigned int WindowsPipeReceiver::GetReceiveResult()
00127 {
00128 if (m_resultPending)
00129 {
00130 HANDLE h = GetHandle();
00131 if (GetOverlappedResult(h, &m_overlapped, &m_lastResult, false))
00132 {
00133 if (m_lastResult == 0)
00134 m_eofReceived = true;
00135 }
00136 else
00137 {
00138 switch (GetLastError())
00139 {
00140 default:
00141 CheckAndHandleError("GetOverlappedResult", false);
00142 case ERROR_BROKEN_PIPE:
00143 case ERROR_HANDLE_EOF:
00144 m_lastResult = 0;
00145 m_eofReceived = true;
00146 }
00147 }
00148 m_resultPending = false;
00149 }
00150 return m_lastResult;
00151 }
00152
00153
00154
00155 WindowsPipeSender::WindowsPipeSender()
00156 : m_resultPending(false), m_lastResult(0)
00157 {
00158 m_event.AttachHandle(CreateEvent(NULL, true, false, NULL), true);
00159 CheckAndHandleError("CreateEvent", m_event.HandleValid());
00160 memset(&m_overlapped, 0, sizeof(m_overlapped));
00161 m_overlapped.hEvent = m_event;
00162 }
00163
00164 void WindowsPipeSender::Send(const byte* buf, size_t bufLen)
00165 {
00166 DWORD written = 0;
00167 HANDLE h = GetHandle();
00168
00169 if (WriteFile(h, buf, UnsignedMin((DWORD)128*1024, bufLen), &written, &m_overlapped))
00170 {
00171 m_resultPending = false;
00172 m_lastResult = written;
00173 }
00174 else
00175 {
00176 if (GetLastError() != ERROR_IO_PENDING)
00177 CheckAndHandleError("WriteFile", false);
00178
00179 m_resultPending = true;
00180 }
00181 }
00182
00183 void WindowsPipeSender::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
00184 {
00185 if (m_resultPending)
00186 container.AddHandle(m_event, CallStack("WindowsPipeSender::GetWaitObjects() - result pending", &callStack));
00187 else
00188 container.SetNoWait(CallStack("WindowsPipeSender::GetWaitObjects() - result ready", &callStack));
00189 }
00190
00191 unsigned int WindowsPipeSender::GetSendResult()
00192 {
00193 if (m_resultPending)
00194 {
00195 HANDLE h = GetHandle();
00196 BOOL result = GetOverlappedResult(h, &m_overlapped, &m_lastResult, false);
00197 CheckAndHandleError("GetOverlappedResult", result);
00198 m_resultPending = false;
00199 }
00200 return m_lastResult;
00201 }
00202
00203 NAMESPACE_END
00204
00205 #endif