Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

# winpipes.cpp

    00001 // winpipes.cpp - written and placed in the public domain by Wei Dai
    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