connect_pipe.ipp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. //
  2. // impl/connect_pipe.ipp
  3. // ~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2023 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 ASIO_IMPL_CONNECT_PIPE_IPP
  13. #define 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 "asio/detail/config.hpp"
  18. #if defined(ASIO_HAS_PIPE)
  19. #include "asio/connect_pipe.hpp"
  20. #if defined(ASIO_HAS_IOCP)
  21. # include <cstdio>
  22. # if _WIN32_WINNT >= 0x601
  23. # include <bcrypt.h>
  24. # if !defined(ASIO_NO_DEFAULT_LINKED_LIBS)
  25. # if defined(_MSC_VER)
  26. # pragma comment(lib, "bcrypt.lib")
  27. # endif // defined(_MSC_VER)
  28. # endif // !defined(ASIO_NO_DEFAULT_LINKED_LIBS)
  29. # endif // _WIN32_WINNT >= 0x601
  30. #else // defined(ASIO_HAS_IOCP)
  31. # include "asio/detail/descriptor_ops.hpp"
  32. #endif // defined(ASIO_HAS_IOCP)
  33. #include "asio/detail/push_options.hpp"
  34. namespace asio {
  35. namespace detail {
  36. void create_pipe(native_pipe_handle p[2], asio::error_code& ec)
  37. {
  38. #if defined(ASIO_HAS_IOCP)
  39. using namespace std; // For sprintf and memcmp.
  40. static long counter1 = 0;
  41. static long counter2 = 0;
  42. long n1 = ::InterlockedIncrement(&counter1);
  43. long n2 = (static_cast<unsigned long>(n1) % 0x10000000) == 0
  44. ? ::InterlockedIncrement(&counter2)
  45. : ::InterlockedExchangeAdd(&counter2, 0);
  46. wchar_t pipe_name[128];
  47. #if defined(ASIO_HAS_SECURE_RTL)
  48. swprintf_s(
  49. #else // defined(ASIO_HAS_SECURE_RTL)
  50. _snwprintf(
  51. #endif // defined(ASIO_HAS_SECURE_RTL)
  52. pipe_name, 128,
  53. L"\\\\.\\pipe\\asio-A0812896-741A-484D-AF23-BE51BF620E22-%u-%ld-%ld",
  54. static_cast<unsigned int>(::GetCurrentProcessId()), n1, n2);
  55. p[0] = ::CreateNamedPipeW(pipe_name,
  56. PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
  57. 0, 1, 8192, 8192, 0, 0);
  58. if (p[0] == INVALID_HANDLE_VALUE)
  59. {
  60. DWORD last_error = ::GetLastError();
  61. ec.assign(last_error, asio::error::get_system_category());
  62. return;
  63. }
  64. p[1] = ::CreateFileW(pipe_name, GENERIC_WRITE, 0,
  65. 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
  66. if (p[1] == INVALID_HANDLE_VALUE)
  67. {
  68. DWORD last_error = ::GetLastError();
  69. ::CloseHandle(p[0]);
  70. ec.assign(last_error, asio::error::get_system_category());
  71. return;
  72. }
  73. # if _WIN32_WINNT >= 0x601
  74. unsigned char nonce[16];
  75. if (::BCryptGenRandom(0, nonce, sizeof(nonce),
  76. BCRYPT_USE_SYSTEM_PREFERRED_RNG) != 0)
  77. {
  78. ec = asio::error::connection_aborted;
  79. ::CloseHandle(p[0]);
  80. ::CloseHandle(p[1]);
  81. return;
  82. }
  83. DWORD bytes_written = 0;
  84. BOOL ok = ::WriteFile(p[1], nonce, sizeof(nonce), &bytes_written, 0);
  85. if (!ok || bytes_written != sizeof(nonce))
  86. {
  87. ec = asio::error::connection_aborted;
  88. ::CloseHandle(p[0]);
  89. ::CloseHandle(p[1]);
  90. return;
  91. }
  92. unsigned char nonce_check[sizeof(nonce)];
  93. DWORD bytes_read = 0;
  94. ok = ::ReadFile(p[0], nonce_check, sizeof(nonce), &bytes_read, 0);
  95. if (!ok || bytes_read != sizeof(nonce)
  96. || memcmp(nonce, nonce_check, sizeof(nonce)) != 0)
  97. {
  98. ec = asio::error::connection_aborted;
  99. ::CloseHandle(p[0]);
  100. ::CloseHandle(p[1]);
  101. return;
  102. }
  103. #endif // _WIN32_WINNT >= 0x601
  104. asio::error::clear(ec);
  105. #else // defined(ASIO_HAS_IOCP)
  106. int result = ::pipe(p);
  107. detail::descriptor_ops::get_last_error(ec, result != 0);
  108. #endif // defined(ASIO_HAS_IOCP)
  109. }
  110. void close_pipe(native_pipe_handle p)
  111. {
  112. #if defined(ASIO_HAS_IOCP)
  113. ::CloseHandle(p);
  114. #else // defined(ASIO_HAS_IOCP)
  115. asio::error_code ignored_ec;
  116. detail::descriptor_ops::state_type state = 0;
  117. detail::descriptor_ops::close(p, state, ignored_ec);
  118. #endif // defined(ASIO_HAS_IOCP)
  119. }
  120. } // namespace detail
  121. } // namespace asio
  122. #include "asio/detail/pop_options.hpp"
  123. #endif // defined(ASIO_HAS_PIPE)
  124. #endif // ASIO_IMPL_CONNECT_PIPE_IPP