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

Side by Side 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.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 #include "..\engine\stdafx.h" 1 #include <Windows.h>
2
3 #include <Lmcons.h> 2 #include <Lmcons.h>
3 #include <Sddl.h>
4 4
5 #include "Communication.h" 5 #include "Communication.h"
6 6
7 namespace 7 namespace
8 { 8 {
9 std::string AppendErrorCode(const std::string& message)
10 {
11 std::stringstream stream;
12 stream << message << " (Error code: " << GetLastError() << ")";
13 return stream.str();
14 }
15
9 std::wstring GetUserName() 16 std::wstring GetUserName()
10 { 17 {
11 const DWORD maxLength = UNLEN + 1; 18 const DWORD maxLength = UNLEN + 1;
12 std::auto_ptr<wchar_t> buffer(new wchar_t[maxLength]); 19 std::auto_ptr<wchar_t> buffer(new wchar_t[maxLength]);
13 DWORD length = maxLength; 20 DWORD length = maxLength;
14 if (!::GetUserName(buffer.get(), &length)) 21 if (!::GetUserNameW(buffer.get(), &length))
Felix Dahlke 2013/06/04 06:39:39 Agreed, we should do that with all the other calls
15 { 22 throw std::runtime_error(AppendErrorCode("Failed to get the current user's name"));
16 std::stringstream stream;
17 stream << "Failed to get the current user's name (Error code: " << GetLast Error() << ")";
18 throw std::runtime_error("Failed to get the current user's name");
19 }
20 return std::wstring(buffer.get(), length); 23 return std::wstring(buffer.get(), length);
21 } 24 }
22 } 25 }
23 26
24 const std::wstring Communication::pipeName = L"\\\\.\\pipe\\adblockplusengine_" + GetUserName(); 27 const std::wstring Communication::pipeName = L"\\\\.\\pipe\\adblockplusengine_" + GetUserName();
25 28
26 Communication::InputBuffer Communication::ReadMessage(HANDLE pipe) 29 Communication::PipeConnectionError::PipeConnectionError()
30 : std::runtime_error(AppendErrorCode("Unable to connect to a named pipe"))
31 {
32 }
33
34 Communication::Pipe::Pipe(const std::wstring& pipeName, Communication::Pipe::Mod e mode)
35 {
36 pipe = INVALID_HANDLE_VALUE;
37 if (mode == MODE_CREATE)
38 {
39 SECURITY_ATTRIBUTES sa;
40 memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
41 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
42
43 // Low mandatory label. See http://msdn.microsoft.com/en-us/library/bb625958 .aspx
44 LPCWSTR accessControlEntry = L"S:(ML;;NW;;;LW)";
45 PSECURITY_DESCRIPTOR securitydescriptor;
46 ConvertStringSecurityDescriptorToSecurityDescriptorW(accessControlEntry, SDD L_REVISION_1, &securitydescriptor, 0);
47
48 sa.lpSecurityDescriptor = securitydescriptor;
49 sa.bInheritHandle = TRUE;
50
51 pipe = CreateNamedPipeW (pipeName.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MES SAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
52 PIPE_UNLIMITED_INSTANCES, Communication::buffe rSize, Communication::bufferSize, 0, &sa);
53 LocalFree(securitydescriptor);
54 }
55 else
56 {
57 if (WaitNamedPipeW(pipeName.c_str(), 5000))
58 pipe = CreateFileW(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, O PEN_EXISTING, 0, 0);
59 }
60
61 if (pipe == INVALID_HANDLE_VALUE)
62 throw PipeConnectionError();
63
64 DWORD pipeMode = PIPE_READMODE_MESSAGE | PIPE_WAIT;
65 if (!SetNamedPipeHandleState(pipe, &pipeMode, 0, 0))
66 throw std::runtime_error("SetNamedPipeHandleState failed: error " + GetLastE rror());
67
68 if (mode == MODE_CREATE && !ConnectNamedPipe(pipe, 0))
69 throw std::runtime_error("Client failed to connect: error " + GetLastError() );
70 }
71
72 Communication::Pipe::~Pipe()
73 {
74 CloseHandle(pipe);
75 }
76
77 Communication::InputBuffer Communication::Pipe::ReadMessage()
27 { 78 {
28 std::stringstream stream; 79 std::stringstream stream;
29 std::auto_ptr<char> buffer(new char[bufferSize]); 80 std::auto_ptr<char> buffer(new char[bufferSize]);
30 bool doneReading = false; 81 bool doneReading = false;
31 while (!doneReading) 82 while (!doneReading)
32 { 83 {
33 DWORD bytesRead; 84 DWORD bytesRead;
34 if (ReadFile(pipe, buffer.get(), bufferSize * sizeof(char), &bytesRead, 0)) 85 if (ReadFile(pipe, buffer.get(), bufferSize * sizeof(char), &bytesRead, 0))
35 doneReading = true; 86 doneReading = true;
36 else if (GetLastError() != ERROR_MORE_DATA) 87 else if (GetLastError() != ERROR_MORE_DATA)
37 { 88 {
38 std::stringstream stream; 89 std::stringstream stream;
39 stream << "Error reading from pipe: " << GetLastError(); 90 stream << "Error reading from pipe: " << GetLastError();
40 throw std::runtime_error(stream.str()); 91 throw std::runtime_error(stream.str());
41 } 92 }
42 stream << std::string(buffer.get(), bytesRead); 93 stream << std::string(buffer.get(), bytesRead);
43 } 94 }
44 return Communication::InputBuffer(stream.str()); 95 return Communication::InputBuffer(stream.str());
45 } 96 }
46 97
47 void Communication::WriteMessage(HANDLE pipe, Communication::OutputBuffer& messa ge) 98 void Communication::Pipe::WriteMessage(Communication::OutputBuffer& message)
48 { 99 {
49 DWORD bytesWritten; 100 DWORD bytesWritten;
50 std::string data = message.Get(); 101 std::string data = message.Get();
51 if (!WriteFile(pipe, data.c_str(), data.length(), &bytesWritten, 0)) 102 if (!WriteFile(pipe, data.c_str(), data.length(), &bytesWritten, 0))
52 throw std::runtime_error("Failed to write to pipe"); 103 throw std::runtime_error("Failed to write to pipe");
53 } 104 }
OLDNEW

Powered by Google App Engine
This is Rietveld