libmoost
|
00001 /* vim:set ts=3 sw=3 sts=3 et: */ 00028 #ifndef MOOST_IO_DETAIL_HELPER_WIN32_HPP__ 00029 #define MOOST_IO_DETAIL_HELPER_WIN32_HPP__ 00030 00031 #include <boost/asio.hpp> 00032 #include <windows.h> 00033 #include <strsafe.h> 00034 00035 namespace moost { namespace io { namespace detail { 00036 00037 class helper 00038 { 00039 public: 00040 typedef HANDLE native_io_t; 00041 typedef boost::asio::windows::basic_stream_handle<> async_stream_t; 00042 typedef DWORD error_t; 00043 00044 static native_io_t duplicate(native_io_t in) 00045 { 00046 native_io_t duped; 00047 00048 if (!DuplicateHandle(GetCurrentProcess(), in, GetCurrentProcess(), &duped, 0, FALSE, DUPLICATE_SAME_ACCESS)) 00049 { 00050 throw std::runtime_error("failed to duplicate handle"); 00051 } 00052 00053 return duped; 00054 } 00055 00056 static bool close(native_io_t in) 00057 { 00058 return CloseHandle(in) == TRUE; 00059 } 00060 00061 static void create_pipe(native_io_t& read_end, native_io_t& write_end) 00062 { 00063 /* 00064 * For some strange reason, anonymous pipes, even though they're using named pipes under 00065 * the hood according to the documentation, do not support asynchronous i/o. 00066 * So I'm resorting to creating a named pipe with a unique name here. 00067 */ 00068 00069 unsigned int instance = 0; 00070 const unsigned int max_instances = 100; 00071 std::basic_string<TCHAR> pipename; 00072 native_io_t pipe_read, pipe_write; 00073 00074 while (instance < max_instances) 00075 { 00076 std::basic_stringstream<TCHAR> ss; 00077 ss << TEXT("\\\\.\\pipe\\") << GetCurrentProcessId() << TEXT("\\iohelper") << instance; 00078 pipename = ss.str(); 00079 00080 pipe_write = CreateNamedPipe(pipename.c_str(), PIPE_ACCESS_OUTBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE, 00081 PIPE_TYPE_BYTE | PIPE_WAIT, 1, 64, 64, 0, NULL); 00082 00083 if (pipe_write != INVALID_HANDLE_VALUE) 00084 { 00085 break; 00086 } 00087 00088 ++instance; 00089 } 00090 00091 if (pipe_write == INVALID_HANDLE_VALUE) 00092 { 00093 throw std::runtime_error("failed to create named pipe"); 00094 } 00095 00096 try 00097 { 00098 pipe_read = CreateFile(pipename.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL); 00099 00100 if (pipe_read == INVALID_HANDLE_VALUE) 00101 { 00102 throw std::runtime_error("failed to open named pipe"); 00103 } 00104 } 00105 catch (...) 00106 { 00107 CloseHandle(pipe_write); 00108 00109 throw; 00110 } 00111 00112 read_end = pipe_read; 00113 write_end = pipe_write; 00114 } 00115 00116 static bool write(native_io_t io, const void *data, size_t length, size_t *written) 00117 { 00118 DWORD wr; 00119 00120 bool rv = ::WriteFile(io, data, length, &wr, NULL) == TRUE; 00121 00122 if (written) 00123 { 00124 *written = rv ? static_cast<size_t>(wr) : 0; 00125 } 00126 00127 return rv; 00128 } 00129 00130 static error_t error() 00131 { 00132 return GetLastError(); 00133 } 00134 }; 00135 00136 } } } 00137 00138 #endif