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 bool WindowsPipeReceiver::Receive(byte* buf, unsigned int bufLen) 00090 { 00091 assert(!m_resultPending && !m_eofReceived); 00092 00093 HANDLE h = GetHandle(); 00094 // don't queue too much at once, or we might use up non-paged memory 00095 if (ReadFile(h, buf, STDMIN(bufLen, 128U*1024U), &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) 00119 { 00120 if (m_resultPending) 00121 container.AddHandle(m_event); 00122 else if (!m_eofReceived) 00123 container.SetNoWait(); 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, unsigned int bufLen) 00165 { 00166 DWORD written = 0; 00167 HANDLE h = GetHandle(); 00168 // don't queue too much at once, or we might use up non-paged memory 00169 if (WriteFile(h, buf, STDMIN(bufLen, 128U*1024U), &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) 00184 { 00185 if (m_resultPending) 00186 container.AddHandle(m_event); 00187 else 00188 container.SetNoWait(); 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

Generated on Fri Aug 27 15:51:14 2004 for Crypto++ by doxygen 1.3.8