connect_pipe.ipp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. //
  2. // impl/connect_pipe.ipp
  3. // ~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2025 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. // Copyright (c) 2021 Klemens D. Morgenstern
  7. // (klemens dot morgenstern at gmx dot net)
  8. //
  9. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  10. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  11. //
  12. #ifndef BOOST_ASIO_IMPL_CONNECT_PIPE_IPP
  13. #define BOOST_ASIO_IMPL_CONNECT_PIPE_IPP
  14. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. # pragma once
  16. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  17. #include <boost/asio/detail/config.hpp>
  18. #if defined(BOOST_ASIO_HAS_PIPE)
  19. #include <boost/asio/connect_pipe.hpp>
  20. #if defined(BOOST_ASIO_HAS_IOCP)
  21. # include <cstdio>
  22. # if _WIN32_WINNT >= 0x601
  23. # include <bcrypt.h>
  24. # if !defined(BOOST_ASIO_NO_DEFAULT_LINKED_LIBS)
  25. # if defined(_MSC_VER)
  26. # pragma comment(lib, "bcrypt.lib")
  27. # endif // defined(_MSC_VER)
  28. # endif // !defined(BOOST_ASIO_NO_DEFAULT_LINKED_LIBS)
  29. # endif // _WIN32_WINNT >= 0x601
  30. #else // defined(BOOST_ASIO_HAS_IOCP)
  31. # include <boost/asio/detail/descriptor_ops.hpp>
  32. #endif // defined(BOOST_ASIO_HAS_IOCP)
  33. #include <boost/asio/detail/push_options.hpp>
  34. namespace boost {
  35. namespace asio {
  36. namespace detail {
  37. void create_pipe(native_pipe_handle p[2], boost::system::error_code& ec)
  38. {
  39. #if defined(BOOST_ASIO_HAS_IOCP)
  40. using namespace std; // For sprintf and memcmp.
  41. static long counter1 = 0;
  42. static long counter2 = 0;
  43. long n1 = ::InterlockedIncrement(&counter1);
  44. long n2 = (static_cast<unsigned long>(n1) % 0x10000000) == 0
  45. ? ::InterlockedIncrement(&counter2)
  46. : ::InterlockedExchangeAdd(&counter2, 0);
  47. wchar_t pipe_name[128];
  48. #if defined(BOOST_ASIO_HAS_SECURE_RTL)
  49. swprintf_s(
  50. #else // defined(BOOST_ASIO_HAS_SECURE_RTL)
  51. _snwprintf(
  52. #endif // defined(BOOST_ASIO_HAS_SECURE_RTL)
  53. pipe_name, 128,
  54. // Include address of static to discriminate asio instances in DLLs.
  55. L"\\\\.\\pipe\\asio-A0812896-741A-484D-AF23-BE51BF620E22-%u-%p-%ld-%ld",
  56. static_cast<unsigned int>(::GetCurrentProcessId()), &counter1, n1, n2);
  57. p[0] = ::CreateNamedPipeW(pipe_name,
  58. PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
  59. 0, 1, 8192, 8192, 0, 0);
  60. if (p[0] == INVALID_HANDLE_VALUE)
  61. {
  62. DWORD last_error = ::GetLastError();
  63. ec.assign(last_error, boost::asio::error::get_system_category());
  64. return;
  65. }
  66. p[1] = ::CreateFileW(pipe_name, GENERIC_WRITE, 0,
  67. 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
  68. if (p[1] == INVALID_HANDLE_VALUE)
  69. {
  70. DWORD last_error = ::GetLastError();
  71. ::CloseHandle(p[0]);
  72. ec.assign(last_error, boost::asio::error::get_system_category());
  73. return;
  74. }
  75. # if _WIN32_WINNT >= 0x601
  76. unsigned char nonce[16];
  77. if (::BCryptGenRandom(0, nonce, sizeof(nonce),
  78. BCRYPT_USE_SYSTEM_PREFERRED_RNG) != 0)
  79. {
  80. ec = boost::asio::error::connection_aborted;
  81. ::CloseHandle(p[0]);
  82. ::CloseHandle(p[1]);
  83. return;
  84. }
  85. DWORD bytes_written = 0;
  86. BOOL ok = ::WriteFile(p[1], nonce, sizeof(nonce), &bytes_written, 0);
  87. if (!ok || bytes_written != sizeof(nonce))
  88. {
  89. ec = boost::asio::error::connection_aborted;
  90. ::CloseHandle(p[0]);
  91. ::CloseHandle(p[1]);
  92. return;
  93. }
  94. unsigned char nonce_check[sizeof(nonce)];
  95. DWORD bytes_read = 0;
  96. ok = ::ReadFile(p[0], nonce_check, sizeof(nonce), &bytes_read, 0);
  97. if (!ok || bytes_read != sizeof(nonce)
  98. || memcmp(nonce, nonce_check, sizeof(nonce)) != 0)
  99. {
  100. ec = boost::asio::error::connection_aborted;
  101. ::CloseHandle(p[0]);
  102. ::CloseHandle(p[1]);
  103. return;
  104. }
  105. #endif // _WIN32_WINNT >= 0x601
  106. boost::asio::error::clear(ec);
  107. #else // defined(BOOST_ASIO_HAS_IOCP)
  108. int result = ::pipe(p);
  109. detail::descriptor_ops::get_last_error(ec, result != 0);
  110. #endif // defined(BOOST_ASIO_HAS_IOCP)
  111. }
  112. void close_pipe(native_pipe_handle p)
  113. {
  114. #if defined(BOOST_ASIO_HAS_IOCP)
  115. ::CloseHandle(p);
  116. #else // defined(BOOST_ASIO_HAS_IOCP)
  117. boost::system::error_code ignored_ec;
  118. detail::descriptor_ops::state_type state = 0;
  119. detail::descriptor_ops::close(p, state, ignored_ec);
  120. #endif // defined(BOOST_ASIO_HAS_IOCP)
  121. }
  122. } // namespace detail
  123. } // namespace asio
  124. } // namespace boost
  125. #include <boost/asio/detail/pop_options.hpp>
  126. #endif // defined(BOOST_ASIO_HAS_PIPE)
  127. #endif // BOOST_ASIO_IMPL_CONNECT_PIPE_IPP