Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class 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

Generated on Sun Mar 14 20:44:29 2004 for Crypto++ by doxygen 1.3.6-20040222