| Index: handler/win/registration_pipe_state.cc
|
| diff --git a/handler/win/registration_pipe_state.cc b/handler/win/registration_pipe_state.cc
|
| deleted file mode 100644
|
| index 08d265f1ce871ff444bc1dfab645788375f13af5..0000000000000000000000000000000000000000
|
| --- a/handler/win/registration_pipe_state.cc
|
| +++ /dev/null
|
| @@ -1,289 +0,0 @@
|
| -// Copyright 2015 The Crashpad Authors. All rights reserved.
|
| -//
|
| -// Licensed under the Apache License, Version 2.0 (the "License");
|
| -// you may not use this file except in compliance with the License.
|
| -// You may obtain a copy of the License at
|
| -//
|
| -// http://www.apache.org/licenses/LICENSE-2.0
|
| -//
|
| -// Unless required by applicable law or agreed to in writing, software
|
| -// distributed under the License is distributed on an "AS IS" BASIS,
|
| -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| -// See the License for the specific language governing permissions and
|
| -// limitations under the License.
|
| -
|
| -#include "handler/win/registration_pipe_state.h"
|
| -
|
| -#include <string.h>
|
| -
|
| -#include <vector>
|
| -
|
| -#include "base/logging.h"
|
| -#include "base/memory/scoped_ptr.h"
|
| -#include "util/stdlib/pointer_container.h"
|
| -
|
| -namespace crashpad {
|
| -
|
| -RegistrationPipeState::RegistrationPipeState(
|
| - ScopedFileHANDLE pipe,
|
| - RegistrationServer::Delegate* delegate)
|
| - : request_(),
|
| - response_(),
|
| - completion_handler_(nullptr),
|
| - overlapped_(),
|
| - event_(),
|
| - pipe_(pipe.Pass()),
|
| - waiting_for_close_(false),
|
| - delegate_(delegate),
|
| - get_named_pipe_client_process_id_proc_(nullptr) {
|
| - HMODULE kernel_dll = GetModuleHandle(L"kernel32.dll");
|
| - if (kernel_dll) {
|
| - get_named_pipe_client_process_id_proc_ =
|
| - reinterpret_cast<decltype(GetNamedPipeClientProcessId)*>(
|
| - GetProcAddress(kernel_dll, "GetNamedPipeClientProcessId"));
|
| - }
|
| -}
|
| -
|
| -RegistrationPipeState::~RegistrationPipeState() {
|
| -}
|
| -
|
| -bool RegistrationPipeState::Initialize() {
|
| - DCHECK(!event_.is_valid());
|
| - DCHECK(pipe_.is_valid());
|
| -
|
| - event_.reset(CreateEvent(nullptr, true, false, nullptr));
|
| -
|
| - if (!event_.is_valid()) {
|
| - PLOG(ERROR) << "CreateEvent";
|
| - } else {
|
| - overlapped_.hEvent = event_.get();
|
| - if (IssueConnect())
|
| - return true;
|
| - }
|
| -
|
| - overlapped_.hEvent = nullptr;
|
| - event_.reset();
|
| - pipe_.reset();
|
| - completion_handler_ = nullptr;
|
| -
|
| - return false;
|
| -}
|
| -
|
| -void RegistrationPipeState::Stop() {
|
| - DCHECK(pipe_.is_valid());
|
| - if (!CancelIo(pipe_.get()))
|
| - PLOG(FATAL) << "CancelIo";
|
| -}
|
| -
|
| -bool RegistrationPipeState::OnCompletion() {
|
| - AsyncCompletionHandler completion_handler = completion_handler_;
|
| - completion_handler_ = nullptr;
|
| -
|
| - DWORD bytes_transferred = 0;
|
| - BOOL success = GetOverlappedResult(pipe_.get(),
|
| - &overlapped_,
|
| - &bytes_transferred,
|
| - false); // Do not wait.
|
| - if (!success) {
|
| - // ERROR_BROKEN_PIPE is expected when we are waiting for the client to close
|
| - // the pipe (signaling that they are done reading the response).
|
| - if (!waiting_for_close_ || GetLastError() != ERROR_BROKEN_PIPE)
|
| - PLOG(ERROR) << "GetOverlappedResult";
|
| - }
|
| -
|
| - bool still_running = false;
|
| - if (!ResetEvent(event_.get())) {
|
| - PLOG(ERROR) << "ResetEvent";
|
| - } else if (!completion_handler) {
|
| - NOTREACHED();
|
| - still_running = ResetConnection();
|
| - } else if (!success) {
|
| - still_running = ResetConnection();
|
| - } else {
|
| - still_running = (this->*completion_handler)(bytes_transferred);
|
| - }
|
| -
|
| - if (!still_running) {
|
| - overlapped_.hEvent = nullptr;
|
| - event_.reset();
|
| - pipe_.reset();
|
| - completion_handler_ = nullptr;
|
| - } else {
|
| - DCHECK(completion_handler_);
|
| - }
|
| -
|
| - return still_running;
|
| -}
|
| -
|
| -bool RegistrationPipeState::OnConnectComplete(DWORD /* bytes_transferred */) {
|
| - return IssueRead();
|
| -}
|
| -
|
| -bool RegistrationPipeState::OnReadComplete(DWORD bytes_transferred) {
|
| - if (bytes_transferred != sizeof(request_)) {
|
| - LOG(ERROR) << "Invalid message size: " << bytes_transferred;
|
| - return ResetConnection();
|
| - } else {
|
| - return HandleRequest();
|
| - }
|
| -}
|
| -
|
| -bool RegistrationPipeState::OnWriteComplete(DWORD bytes_transferred) {
|
| - if (bytes_transferred != sizeof(response_)) {
|
| - LOG(ERROR) << "Incomplete write operation. Bytes written: "
|
| - << bytes_transferred;
|
| - }
|
| -
|
| - return IssueWaitForClientClose();
|
| -}
|
| -
|
| -bool RegistrationPipeState::OnWaitForClientCloseComplete(
|
| - DWORD bytes_transferred) {
|
| - LOG(ERROR) << "Unexpected extra data (" << bytes_transferred
|
| - << " bytes) received from client.";
|
| - return ResetConnection();
|
| -}
|
| -
|
| -bool RegistrationPipeState::IssueConnect() {
|
| - if (ConnectNamedPipe(pipe_.get(), &overlapped_)) {
|
| - return OnConnectComplete(0); // bytes_transferred (ignored)
|
| - } else {
|
| - DWORD result = GetLastError();
|
| - if (result == ERROR_PIPE_CONNECTED) {
|
| - return OnConnectComplete(0); // bytes_transferred (ignored)
|
| - } else if (result == ERROR_IO_PENDING) {
|
| - completion_handler_ = &RegistrationPipeState::OnConnectComplete;
|
| - return true;
|
| - } else {
|
| - PLOG(ERROR) << "ConnectNamedPipe";
|
| - return false;
|
| - }
|
| - }
|
| -}
|
| -
|
| -bool RegistrationPipeState::IssueRead() {
|
| - DWORD bytes_read = 0;
|
| - if (ReadFile(pipe_.get(),
|
| - &request_,
|
| - sizeof(request_),
|
| - &bytes_read,
|
| - &overlapped_)) {
|
| - return OnReadComplete(bytes_read);
|
| - } else if (GetLastError() == ERROR_IO_PENDING) {
|
| - completion_handler_ = &RegistrationPipeState::OnReadComplete;
|
| - return true;
|
| - } else {
|
| - PLOG(ERROR) << "ReadFile";
|
| - return ResetConnection();
|
| - }
|
| -}
|
| -
|
| -bool RegistrationPipeState::IssueWrite() {
|
| - DWORD bytes_written = 0;
|
| - if (WriteFile(pipe_.get(),
|
| - &response_,
|
| - sizeof(response_),
|
| - &bytes_written,
|
| - &overlapped_)) {
|
| - return OnWriteComplete(bytes_written);
|
| - } else if (GetLastError() == ERROR_IO_PENDING) {
|
| - completion_handler_ = &RegistrationPipeState::OnWriteComplete;
|
| - return true;
|
| - } else {
|
| - PLOG(ERROR) << "WriteFile";
|
| - return ResetConnection();
|
| - }
|
| -}
|
| -
|
| -bool RegistrationPipeState::IssueWaitForClientClose() {
|
| - // If we invoke DisconnectNamedPipe before the client has read the response
|
| - // the response will never be delivered. Therefore we issue an extra ReadFile
|
| - // operation after writing the response. No data is expected - the operation
|
| - // will be 'completed' when the client closes the pipe.
|
| - waiting_for_close_ = true;
|
| - DWORD bytes_read = 0;
|
| - if (ReadFile(pipe_.get(),
|
| - &request_,
|
| - sizeof(request_),
|
| - &bytes_read,
|
| - &overlapped_)) {
|
| - return OnWaitForClientCloseComplete(bytes_read);
|
| - } else if (GetLastError() == ERROR_IO_PENDING) {
|
| - completion_handler_ = &RegistrationPipeState::OnWaitForClientCloseComplete;
|
| - return true;
|
| - } else {
|
| - PLOG(ERROR) << "ReadFile";
|
| - return ResetConnection();
|
| - }
|
| -}
|
| -
|
| -bool RegistrationPipeState::HandleRequest() {
|
| - if (get_named_pipe_client_process_id_proc_) {
|
| - // On Vista+ we can verify that the client is who they claim to be, thus
|
| - // preventing arbitrary processes from having us duplicate handles into
|
| - // other processes.
|
| - DWORD real_client_process_id = 0;
|
| - if (!get_named_pipe_client_process_id_proc_(pipe_.get(),
|
| - &real_client_process_id)) {
|
| - PLOG(ERROR) << "GetNamedPipeClientProcessId";
|
| - } else if (real_client_process_id != request_.client_process_id) {
|
| - LOG(ERROR) << "Client process ID from request ("
|
| - << request_.client_process_id
|
| - << ") does not match pipe client process ID ("
|
| - << real_client_process_id << ").";
|
| - return ResetConnection();
|
| - }
|
| - }
|
| -
|
| - ScopedKernelHANDLE client_process(
|
| - OpenProcess(PROCESS_ALL_ACCESS, false, request_.client_process_id));
|
| - if (!client_process.is_valid()) {
|
| - if (ImpersonateNamedPipeClient(pipe_.get())) {
|
| - client_process.reset(
|
| - OpenProcess(PROCESS_ALL_ACCESS, false, request_.client_process_id));
|
| - RevertToSelf();
|
| - }
|
| - }
|
| -
|
| - if (!client_process.is_valid()) {
|
| - LOG(ERROR) << "Failed to open client process.";
|
| - return ResetConnection();
|
| - }
|
| -
|
| - memset(&response_, 0, sizeof(response_));
|
| -
|
| - HANDLE request_report_event = nullptr;
|
| - HANDLE report_complete_event = nullptr;
|
| -
|
| - if (!delegate_->RegisterClient(client_process.Pass(),
|
| - request_.crashpad_info_address,
|
| - &request_report_event,
|
| - &report_complete_event)) {
|
| - return ResetConnection();
|
| - }
|
| -
|
| - // A handle has at most 32 significant bits, though its type is void*. Thus we
|
| - // truncate it here. An interesting exception is INVALID_HANDLE_VALUE, which
|
| - // is '-1'. It is still safe to truncate it from 0xFFFFFFFFFFFFFFFF to
|
| - // 0xFFFFFFFF, but a 64-bit client receiving that value must correctly sign
|
| - // extend it.
|
| - response_.request_report_event =
|
| - reinterpret_cast<uint32_t>(request_report_event);
|
| - response_.report_complete_event =
|
| - reinterpret_cast<uint32_t>(report_complete_event);
|
| - return IssueWrite();
|
| -}
|
| -
|
| -bool RegistrationPipeState::ResetConnection() {
|
| - memset(&request_, 0, sizeof(request_));
|
| - waiting_for_close_ = false;
|
| -
|
| - if (!DisconnectNamedPipe(pipe_.get())) {
|
| - PLOG(ERROR) << "DisconnectNamedPipe";
|
| - return false;
|
| - } else {
|
| - return IssueConnect();
|
| - }
|
| -}
|
| -
|
| -} // namespace crashpad
|
|
|