Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: src/shared/Communication.cpp

Issue 10786016: Moved all pipe functionality into a self-containing Communication::Pipe class (Closed)
Patch Set: Created May 31, 2013, 11:48 a.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/shared/Communication.cpp
===================================================================
--- a/src/shared/Communication.cpp
+++ b/src/shared/Communication.cpp
@@ -1,34 +1,85 @@
-#include "..\engine\stdafx.h"
-
+#include <Windows.h>
#include <Lmcons.h>
+#include <Sddl.h>
#include "Communication.h"
namespace
{
+ std::string AppendErrorCode(const std::string& message)
+ {
+ std::stringstream stream;
+ stream << message << " (Error code: " << GetLastError() << ")";
+ return stream.str();
+ }
+
std::wstring GetUserName()
{
const DWORD maxLength = UNLEN + 1;
std::auto_ptr<wchar_t> buffer(new wchar_t[maxLength]);
DWORD length = maxLength;
- if (!::GetUserName(buffer.get(), &length))
- {
- std::stringstream stream;
- stream << "Failed to get the current user's name (Error code: " << GetLastError() << ")";
- throw std::runtime_error("Failed to get the current user's name");
- }
+ if (!::GetUserNameW(buffer.get(), &length))
Felix Dahlke 2013/06/04 06:39:39 Agreed, we should do that with all the other calls
+ throw std::runtime_error(AppendErrorCode("Failed to get the current user's name"));
return std::wstring(buffer.get(), length);
}
}
const std::wstring Communication::pipeName = L"\\\\.\\pipe\\adblockplusengine_" + GetUserName();
-Communication::InputBuffer Communication::ReadMessage(HANDLE pipe)
+Communication::PipeConnectionError::PipeConnectionError()
+ : std::runtime_error(AppendErrorCode("Unable to connect to a named pipe"))
+{
+}
+
+Communication::Pipe::Pipe(const std::wstring& pipeName, Communication::Pipe::Mode mode)
+{
+ pipe = INVALID_HANDLE_VALUE;
+ if (mode == MODE_CREATE)
+ {
+ SECURITY_ATTRIBUTES sa;
+ memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
+ sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+
+ // Low mandatory label. See http://msdn.microsoft.com/en-us/library/bb625958.aspx
+ LPCWSTR accessControlEntry = L"S:(ML;;NW;;;LW)";
+ PSECURITY_DESCRIPTOR securitydescriptor;
+ ConvertStringSecurityDescriptorToSecurityDescriptorW(accessControlEntry, SDDL_REVISION_1, &securitydescriptor, 0);
+
+ sa.lpSecurityDescriptor = securitydescriptor;
+ sa.bInheritHandle = TRUE;
+
+ pipe = CreateNamedPipeW (pipeName.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
+ PIPE_UNLIMITED_INSTANCES, Communication::bufferSize, Communication::bufferSize, 0, &sa);
+ LocalFree(securitydescriptor);
+ }
+ else
+ {
+ if (WaitNamedPipeW(pipeName.c_str(), 5000))
+ pipe = CreateFileW(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
+ }
+
+ if (pipe == INVALID_HANDLE_VALUE)
+ throw PipeConnectionError();
+
+ DWORD pipeMode = PIPE_READMODE_MESSAGE | PIPE_WAIT;
+ if (!SetNamedPipeHandleState(pipe, &pipeMode, 0, 0))
+ throw std::runtime_error("SetNamedPipeHandleState failed: error " + GetLastError());
+
+ if (mode == MODE_CREATE && !ConnectNamedPipe(pipe, 0))
+ throw std::runtime_error("Client failed to connect: error " + GetLastError());
+}
+
+Communication::Pipe::~Pipe()
+{
+ CloseHandle(pipe);
+}
+
+Communication::InputBuffer Communication::Pipe::ReadMessage()
{
std::stringstream stream;
std::auto_ptr<char> buffer(new char[bufferSize]);
bool doneReading = false;
while (!doneReading)
{
DWORD bytesRead;
if (ReadFile(pipe, buffer.get(), bufferSize * sizeof(char), &bytesRead, 0))
@@ -39,15 +90,15 @@ Communication::InputBuffer Communication
stream << "Error reading from pipe: " << GetLastError();
throw std::runtime_error(stream.str());
}
stream << std::string(buffer.get(), bytesRead);
}
return Communication::InputBuffer(stream.str());
}
-void Communication::WriteMessage(HANDLE pipe, Communication::OutputBuffer& message)
+void Communication::Pipe::WriteMessage(Communication::OutputBuffer& message)
{
DWORD bytesWritten;
std::string data = message.Get();
if (!WriteFile(pipe, data.c_str(), data.length(), &bytesWritten, 0))
throw std::runtime_error("Failed to write to pipe");
}

Powered by Google App Engine
This is Rietveld