pipe_win.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. // Copyright (c) 2010 Google Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "pipe_win.h"
  15. #include <Sddl.h>
  16. #include <AccCtrl.h>
  17. #include <Aclapi.h>
  18. namespace {
  19. const wchar_t kPipePrefix[] = L"\\\\.\\pipe\\";
  20. const int kPipeBufferSz = 4 * 1024;
  21. } // namespace
  22. bool checkIntegritySupport() {
  23. OSVERSIONINFO osvi;
  24. ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
  25. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  26. GetVersionEx(&osvi);
  27. return osvi.dwMajorVersion > 5;
  28. }
  29. LONG g_pipe_seq = 0;
  30. HANDLE PipePair::OpenPipeServer(const wchar_t* name, bool low_integrity) {
  31. SECURITY_ATTRIBUTES sa = {0};
  32. SECURITY_ATTRIBUTES *psa = 0;
  33. static const bool is_integrity_supported = checkIntegritySupport();
  34. if (is_integrity_supported && low_integrity) {
  35. psa = &sa;
  36. sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  37. sa.bInheritHandle = TRUE;
  38. if (!ConvertStringSecurityDescriptorToSecurityDescriptor(
  39. TEXT("S:(ML;;NWNR;;;LW)"), SDDL_REVISION_1, &sa.lpSecurityDescriptor, NULL))
  40. return INVALID_HANDLE_VALUE;
  41. }
  42. IPCWString pipename(kPipePrefix);
  43. pipename.append(name);
  44. return ::CreateNamedPipeW(pipename.c_str(), PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE,
  45. PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
  46. 1, kPipeBufferSz, kPipeBufferSz, 200, psa);
  47. }
  48. HANDLE PipePair::OpenPipeClient(const wchar_t* name, bool inherit, bool impersonate) {
  49. IPCWString pipename(kPipePrefix);
  50. pipename.append(name);
  51. SECURITY_ATTRIBUTES sa = {sizeof(sa), NULL, inherit ? TRUE : FALSE};
  52. for (;;) {
  53. DWORD attributes = impersonate ? 0 : SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION;
  54. HANDLE pipe = ::CreateFileW(pipename.c_str(), GENERIC_READ | GENERIC_WRITE, 0, &sa,
  55. OPEN_EXISTING, attributes, NULL);
  56. if (INVALID_HANDLE_VALUE == pipe) {
  57. if (ERROR_PIPE_BUSY != ::GetLastError()) {
  58. return pipe;
  59. }
  60. // wait and retry.
  61. ::Sleep(25);
  62. } else {
  63. // success.
  64. return pipe;
  65. }
  66. }
  67. }
  68. PipePair::PipePair(bool inherit_fd2) : srv_(NULL), cln_(NULL) {
  69. // Come up with a reasonable unique name.
  70. const wchar_t kPipePattern[] = L"ko.%x.%x.%x";
  71. wchar_t name[8*3 + sizeof(kPipePattern)];
  72. ::wsprintfW(name, kPipePattern, ::GetCurrentProcessId(), ::GetTickCount(),
  73. ::InterlockedIncrement(&g_pipe_seq));
  74. HANDLE server = OpenPipeServer(name);
  75. if (INVALID_HANDLE_VALUE == server) {
  76. return;
  77. }
  78. // Don't allow client impersonation.
  79. HANDLE client = OpenPipeClient(name, inherit_fd2, false);
  80. if (INVALID_HANDLE_VALUE == client) {
  81. ::CloseHandle(server);
  82. return;
  83. }
  84. if (!::ConnectNamedPipe(server, NULL)) {
  85. if (ERROR_PIPE_CONNECTED != ::GetLastError()) {
  86. ::CloseHandle(server);
  87. ::CloseHandle(client);
  88. return;
  89. }
  90. }
  91. srv_ = server;
  92. cln_ = client;
  93. }
  94. PipeWin::PipeWin() : pipe_(INVALID_HANDLE_VALUE) {
  95. }
  96. PipeWin::~PipeWin() {
  97. if (pipe_ != INVALID_HANDLE_VALUE) {
  98. ::DisconnectNamedPipe(pipe_); // $$$ disconect is valid on the server side.
  99. ::CloseHandle(pipe_);
  100. }
  101. }
  102. bool PipeWin::OpenClient(HANDLE pipe) {
  103. pipe_ = pipe;
  104. return true;
  105. }
  106. bool PipeWin::OpenServer(HANDLE pipe, bool connect) {
  107. pipe_ = pipe;
  108. if (connect) {
  109. if (!::ConnectNamedPipe(pipe, NULL)) {
  110. if (ERROR_PIPE_CONNECTED != ::GetLastError()) {
  111. return false;
  112. }
  113. }
  114. }
  115. return true;
  116. }
  117. bool PipeWin::Write(const void* buf, size_t sz) {
  118. DWORD written = 0;
  119. return (TRUE == ::WriteFile(pipe_, buf, sz, &written, NULL));
  120. }
  121. bool PipeWin::Read(void* buf, size_t* sz) {
  122. return (TRUE == ::ReadFile(pipe_, buf, *sz, reinterpret_cast<DWORD*>(sz), NULL));
  123. }
  124. char* PipeTransport::Receive(size_t* size) {
  125. if (buf_.size() < kBufferSz)
  126. buf_.resize(kBufferSz);
  127. *size = kBufferSz;
  128. if (!Read(&buf_[0], size))
  129. return NULL;
  130. return &buf_[0];
  131. }