// 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 "util/win/exception_handler_server.h"

#include <stdint.h>
#include <string.h>
#include <sys/types.h>

#include <utility>

#include "base/cxx17_backports.h"
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "base/rand_util.h"
#include "base/strings/utf_string_conversions.h"
#include "util/file/file_writer.h"
#include "util/misc/tri_state.h"
#include "util/misc/uuid.h"
#include "util/win/get_function.h"
#include "util/win/handle.h"
#include "util/win/registration_protocol_win.h"
#include "util/win/safe_terminate_process.h"
#include "util/win/xp_compat.h"

namespace crashpad {

namespace {

decltype(GetNamedPipeClientProcessId)* GetNamedPipeClientProcessIdFunction() {
  static const auto get_named_pipe_client_process_id =
      GET_FUNCTION(L"kernel32.dll", ::GetNamedPipeClientProcessId);
  return get_named_pipe_client_process_id;
}

HANDLE DuplicateEvent(HANDLE process, HANDLE event) {
  HANDLE handle;
  if (DuplicateHandle(GetCurrentProcess(),
                      event,
                      process,
                      &handle,
                      SYNCHRONIZE | EVENT_MODIFY_STATE,
                      false,
                      0)) {
    return handle;
  }
  return nullptr;
}

}  // namespace

namespace internal {

//! \brief Context information for the named pipe handler threads.
class PipeServiceContext {
 public:
  PipeServiceContext(HANDLE port,
                     HANDLE pipe,
                     ExceptionHandlerServer::Delegate* delegate,
                     base::Lock* clients_lock,
                     std::set<internal::ClientData*>* clients,
                     uint64_t shutdown_token)
      : port_(port),
        pipe_(pipe),
        delegate_(delegate),
        clients_lock_(clients_lock),
        clients_(clients),
        shutdown_token_(shutdown_token) {}

  HANDLE port() const { return port_; }
  HANDLE pipe() const { return pipe_.get(); }
  ExceptionHandlerServer::Delegate* delegate() const { return delegate_; }
  base::Lock* clients_lock() const { return clients_lock_; }
  std::set<internal::ClientData*>* clients() const { return clients_; }
  uint64_t shutdown_token() const { return shutdown_token_; }

 private:
  HANDLE port_;  // weak
  ScopedKernelHANDLE pipe_;
  ExceptionHandlerServer::Delegate* delegate_;  // weak
  base::Lock* clients_lock_;  // weak
  std::set<internal::ClientData*>* clients_;  // weak
  uint64_t shutdown_token_;

  DISALLOW_COPY_AND_ASSIGN(PipeServiceContext);
};

//! \brief The context data for registered threadpool waits.
//!
//! This object must be created and destroyed on the main thread. Access must be
//! guarded by use of the lock() with the exception of the threadpool wait
//! variables which are accessed only by the main thread.
class ClientData {
 public:
  ClientData(HANDLE port,
             ExceptionHandlerServer::Delegate* delegate,
             ScopedKernelHANDLE process,
             ScopedKernelHANDLE crash_dump_requested_event,
             ScopedKernelHANDLE non_crash_dump_requested_event,
             ScopedKernelHANDLE non_crash_dump_completed_event,
             WinVMAddress crash_exception_information_address,
             WinVMAddress non_crash_exception_information_address,
             WinVMAddress debug_critical_section_address,
             WAITORTIMERCALLBACK crash_dump_request_callback,
             WAITORTIMERCALLBACK non_crash_dump_request_callback,
             WAITORTIMERCALLBACK process_end_callback)
      : crash_dump_request_thread_pool_wait_(INVALID_HANDLE_VALUE),
        non_crash_dump_request_thread_pool_wait_(INVALID_HANDLE_VALUE),
        process_end_thread_pool_wait_(INVALID_HANDLE_VALUE),
        lock_(),
        port_(port),
        delegate_(delegate),
        crash_dump_requested_event_(std::move(crash_dump_requested_event)),
        non_crash_dump_requested_event_(
            std::move(non_crash_dump_requested_event)),
        non_crash_dump_completed_event_(
            std::move(non_crash_dump_completed_event)),
        process_(std::move(process)),
        crash_exception_information_address_(
            crash_exception_information_address),
        non_crash_exception_information_address_(
            non_crash_exception_information_address),
        debug_critical_section_address_(debug_critical_section_address) {
    RegisterThreadPoolWaits(crash_dump_request_callback,
                            non_crash_dump_request_callback,
                            process_end_callback);
  }

  ~ClientData() {
    // It is important that this only access the threadpool waits (it's called
    // from the main thread) until the waits are unregistered, to ensure that
    // any outstanding callbacks are complete.
    UnregisterThreadPoolWaits();
  }

  base::Lock* lock() { return &lock_; }
  HANDLE port() const { return port_; }
  ExceptionHandlerServer::Delegate* delegate() const { return delegate_; }
  HANDLE crash_dump_requested_event() const {
    return crash_dump_requested_event_.get();
  }
  HANDLE non_crash_dump_requested_event() const {
    return non_crash_dump_requested_event_.get();
  }
  HANDLE non_crash_dump_completed_event() const {
    return non_crash_dump_completed_event_.get();
  }
  WinVMAddress crash_exception_information_address() const {
    return crash_exception_information_address_;
  }
  WinVMAddress non_crash_exception_information_address() const {
    return non_crash_exception_information_address_;
  }
  WinVMAddress debug_critical_section_address() const {
    return debug_critical_section_address_;
  }
  HANDLE process() const { return process_.get(); }

 private:
  void RegisterThreadPoolWaits(
      WAITORTIMERCALLBACK crash_dump_request_callback,
      WAITORTIMERCALLBACK non_crash_dump_request_callback,
      WAITORTIMERCALLBACK process_end_callback) {
    if (!RegisterWaitForSingleObject(&crash_dump_request_thread_pool_wait_,
                                     crash_dump_requested_event_.get(),
                                     crash_dump_request_callback,
                                     this,
                                     INFINITE,
                                     WT_EXECUTEDEFAULT)) {
      LOG(ERROR) << "RegisterWaitForSingleObject crash dump requested";
    }

    if (!RegisterWaitForSingleObject(&non_crash_dump_request_thread_pool_wait_,
                                     non_crash_dump_requested_event_.get(),
                                     non_crash_dump_request_callback,
                                     this,
                                     INFINITE,
                                     WT_EXECUTEDEFAULT)) {
      LOG(ERROR) << "RegisterWaitForSingleObject non-crash dump requested";
    }

    if (!RegisterWaitForSingleObject(&process_end_thread_pool_wait_,
                                     process_.get(),
                                     process_end_callback,
                                     this,
                                     INFINITE,
                                     WT_EXECUTEONLYONCE)) {
      LOG(ERROR) << "RegisterWaitForSingleObject process end";
    }
  }

  // This blocks until outstanding calls complete so that we know it's safe to
  // delete this object. Because of this, it must be executed on the main
  // thread, not a threadpool thread.
  void UnregisterThreadPoolWaits() {
    UnregisterWaitEx(crash_dump_request_thread_pool_wait_,
                     INVALID_HANDLE_VALUE);
    crash_dump_request_thread_pool_wait_ = INVALID_HANDLE_VALUE;
    UnregisterWaitEx(non_crash_dump_request_thread_pool_wait_,
                     INVALID_HANDLE_VALUE);
    non_crash_dump_request_thread_pool_wait_ = INVALID_HANDLE_VALUE;
    UnregisterWaitEx(process_end_thread_pool_wait_, INVALID_HANDLE_VALUE);
    process_end_thread_pool_wait_ = INVALID_HANDLE_VALUE;
  }

  // These are only accessed on the main thread.
  HANDLE crash_dump_request_thread_pool_wait_;
  HANDLE non_crash_dump_request_thread_pool_wait_;
  HANDLE process_end_thread_pool_wait_;

  base::Lock lock_;
  // Access to these fields must be guarded by lock_.
  HANDLE port_;  // weak
  ExceptionHandlerServer::Delegate* delegate_;  // weak
  ScopedKernelHANDLE crash_dump_requested_event_;
  ScopedKernelHANDLE non_crash_dump_requested_event_;
  ScopedKernelHANDLE non_crash_dump_completed_event_;
  ScopedKernelHANDLE process_;
  WinVMAddress crash_exception_information_address_;
  WinVMAddress non_crash_exception_information_address_;
  WinVMAddress debug_critical_section_address_;

  DISALLOW_COPY_AND_ASSIGN(ClientData);
};

}  // namespace internal

ExceptionHandlerServer::Delegate::~Delegate() {
}

ExceptionHandlerServer::ExceptionHandlerServer(bool persistent)
    : pipe_name_(),
      port_(CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 1)),
      first_pipe_instance_(),
      clients_lock_(),
      clients_(),
      persistent_(persistent) {
}

ExceptionHandlerServer::~ExceptionHandlerServer() {
}

void ExceptionHandlerServer::SetPipeName(const std::wstring& pipe_name) {
  DCHECK(pipe_name_.empty());
  DCHECK(!pipe_name.empty());

  pipe_name_ = pipe_name;
}

void ExceptionHandlerServer::InitializeWithInheritedDataForInitialClient(
    const InitialClientData& initial_client_data,
    Delegate* delegate) {
  DCHECK(pipe_name_.empty());
  DCHECK(!first_pipe_instance_.is_valid());

  first_pipe_instance_.reset(initial_client_data.first_pipe_instance());

  // TODO(scottmg): Vista+. Might need to pass through or possibly find an Nt*.
  size_t bytes = sizeof(wchar_t) * _MAX_PATH + sizeof(FILE_NAME_INFO);
  std::unique_ptr<uint8_t[]> data(new uint8_t[bytes]);
  if (!GetFileInformationByHandleEx(first_pipe_instance_.get(),
                                    FileNameInfo,
                                    data.get(),
                                    static_cast<DWORD>(bytes))) {
    PLOG(FATAL) << "GetFileInformationByHandleEx";
  }
  FILE_NAME_INFO* file_name_info =
      reinterpret_cast<FILE_NAME_INFO*>(data.get());
  pipe_name_ =
      L"\\\\.\\pipe" + std::wstring(file_name_info->FileName,
                                    file_name_info->FileNameLength /
                                        sizeof(file_name_info->FileName[0]));

  {
    base::AutoLock lock(clients_lock_);
    internal::ClientData* client = new internal::ClientData(
        port_.get(),
        delegate,
        ScopedKernelHANDLE(initial_client_data.client_process()),
        ScopedKernelHANDLE(initial_client_data.request_crash_dump()),
        ScopedKernelHANDLE(initial_client_data.request_non_crash_dump()),
        ScopedKernelHANDLE(initial_client_data.non_crash_dump_completed()),
        initial_client_data.crash_exception_information(),
        initial_client_data.non_crash_exception_information(),
        initial_client_data.debug_critical_section_address(),
        &OnCrashDumpEvent,
        &OnNonCrashDumpEvent,
        &OnProcessEnd);
    clients_.insert(client);
  }
}

void ExceptionHandlerServer::Run(Delegate* delegate) {
  uint64_t shutdown_token = base::RandUint64();
  ScopedKernelHANDLE thread_handles[kPipeInstances];
  for (size_t i = 0; i < base::size(thread_handles); ++i) {
    HANDLE pipe;
    if (first_pipe_instance_.is_valid()) {
      pipe = first_pipe_instance_.release();
    } else {
      pipe = CreateNamedPipeInstance(pipe_name_, i == 0);
      PCHECK(pipe != INVALID_HANDLE_VALUE) << "CreateNamedPipe";
    }

    // Ownership of this object (and the pipe instance) is given to the new
    // thread. We close the thread handles at the end of the scope. They clean
    // up the context object and the pipe instance on termination.
    internal::PipeServiceContext* context =
        new internal::PipeServiceContext(port_.get(),
                                         pipe,
                                         delegate,
                                         &clients_lock_,
                                         &clients_,
                                         shutdown_token);
    thread_handles[i].reset(
        CreateThread(nullptr, 0, &PipeServiceProc, context, 0, nullptr));
    PCHECK(thread_handles[i].is_valid()) << "CreateThread";
  }

  delegate->ExceptionHandlerServerStarted();

  // This is the main loop of the server. Most work is done on the threadpool,
  // other than process end handling which is posted back to this main thread,
  // as we must unregister the threadpool waits here.
  for (;;) {
    OVERLAPPED* ov = nullptr;
    ULONG_PTR key = 0;
    DWORD bytes = 0;
    GetQueuedCompletionStatus(port_.get(), &bytes, &key, &ov, INFINITE);
    if (!key) {
      // Shutting down.
      break;
    }

    // Otherwise, this is a request to unregister and destroy the given client.
    // delete'ing the ClientData blocks in UnregisterWaitEx to ensure all
    // outstanding threadpool waits are complete. This is important because the
    // process handle can be signalled *before* the dump request is signalled.
    internal::ClientData* client = reinterpret_cast<internal::ClientData*>(key);
    base::AutoLock lock(clients_lock_);
    clients_.erase(client);
    delete client;
    if (!persistent_ && clients_.empty())
      break;
  }

  // Signal to the named pipe instances that they should terminate.
  for (size_t i = 0; i < base::size(thread_handles); ++i) {
    ClientToServerMessage message;
    memset(&message, 0, sizeof(message));
    message.type = ClientToServerMessage::kShutdown;
    message.shutdown.token = shutdown_token;
    ServerToClientMessage response;
    SendToCrashHandlerServer(pipe_name_,
                             reinterpret_cast<ClientToServerMessage&>(message),
                             &response);
  }

  for (auto& handle : thread_handles)
    WaitForSingleObject(handle.get(), INFINITE);

  // Deleting ClientData does a blocking wait until the threadpool executions
  // have terminated when unregistering them.
  {
    base::AutoLock lock(clients_lock_);
    for (auto* client : clients_)
      delete client;
    clients_.clear();
  }
}

void ExceptionHandlerServer::Stop() {
  // Post a null key (third argument) to trigger shutdown.
  PostQueuedCompletionStatus(port_.get(), 0, 0, nullptr);
}

// This function must be called with service_context.pipe() already connected to
// a client pipe. It exchanges data with the client and adds a ClientData record
// to service_context->clients().
//
// static
bool ExceptionHandlerServer::ServiceClientConnection(
    const internal::PipeServiceContext& service_context) {
  ClientToServerMessage message;

  if (!LoggingReadFileExactly(
          service_context.pipe(), &message, sizeof(message)))
    return false;

  switch (message.type) {
    case ClientToServerMessage::kShutdown: {
      if (message.shutdown.token != service_context.shutdown_token()) {
        LOG(ERROR) << "forged shutdown request, got: "
                   << message.shutdown.token;
        return false;
      }
      ServerToClientMessage shutdown_response = {};
      LoggingWriteFile(service_context.pipe(),
                       &shutdown_response,
                       sizeof(shutdown_response));
      return true;
    }

    case ClientToServerMessage::kPing: {
      // No action required, the fact that the message was processed is
      // sufficient.
      ServerToClientMessage shutdown_response = {};
      LoggingWriteFile(service_context.pipe(),
                       &shutdown_response,
                       sizeof(shutdown_response));
      return false;
    }

    case ClientToServerMessage::kRegister:
      // Handled below.
      break;

    default:
      LOG(ERROR) << "unhandled message type: " << message.type;
      return false;
  }

  if (message.registration.version != RegistrationRequest::kMessageVersion) {
    LOG(ERROR) << "unexpected version. got: " << message.registration.version
               << " expecting: " << RegistrationRequest::kMessageVersion;
    return false;
  }

  decltype(GetNamedPipeClientProcessId)* get_named_pipe_client_process_id =
      GetNamedPipeClientProcessIdFunction();
  if (get_named_pipe_client_process_id) {
    // GetNamedPipeClientProcessId is only available on Vista+.
    DWORD real_pid = 0;
    if (get_named_pipe_client_process_id(service_context.pipe(), &real_pid) &&
        message.registration.client_process_id != real_pid) {
      LOG(ERROR) << "forged client pid, real pid: " << real_pid
                 << ", got: " << message.registration.client_process_id;
      return false;
    }
  }

  // We attempt to open the process as us. This is the main case that should
  // almost always succeed as the server will generally be more privileged. If
  // we're running as a different user, it may be that we will fail to open
  // the process, but the client will be able to, so we make a second attempt
  // having impersonated the client.
  HANDLE client_process = OpenProcess(
      kXPProcessAllAccess, false, message.registration.client_process_id);
  if (!client_process) {
    if (!ImpersonateNamedPipeClient(service_context.pipe())) {
      PLOG(ERROR) << "ImpersonateNamedPipeClient";
      return false;
    }
    client_process = OpenProcess(
        kXPProcessAllAccess, false, message.registration.client_process_id);
    PCHECK(RevertToSelf());
    if (!client_process) {
      LOG(ERROR) << "failed to open " << message.registration.client_process_id;
      return false;
    }
  }

  internal::ClientData* client;
  {
    base::AutoLock lock(*service_context.clients_lock());
    client = new internal::ClientData(
        service_context.port(),
        service_context.delegate(),
        ScopedKernelHANDLE(client_process),
        ScopedKernelHANDLE(
            CreateEvent(nullptr, false /* auto reset */, false, nullptr)),
        ScopedKernelHANDLE(
            CreateEvent(nullptr, false /* auto reset */, false, nullptr)),
        ScopedKernelHANDLE(
            CreateEvent(nullptr, false /* auto reset */, false, nullptr)),
        message.registration.crash_exception_information,
        message.registration.non_crash_exception_information,
        message.registration.critical_section_address,
        &OnCrashDumpEvent,
        &OnNonCrashDumpEvent,
        &OnProcessEnd);
    service_context.clients()->insert(client);
  }

  // Duplicate the events back to the client so they can request a dump.
  ServerToClientMessage response;
  response.registration.request_crash_dump_event =
      HandleToInt(DuplicateEvent(
          client->process(), client->crash_dump_requested_event()));
  response.registration.request_non_crash_dump_event =
      HandleToInt(DuplicateEvent(
          client->process(), client->non_crash_dump_requested_event()));
  response.registration.non_crash_dump_completed_event =
      HandleToInt(DuplicateEvent(
          client->process(), client->non_crash_dump_completed_event()));

  if (!LoggingWriteFile(service_context.pipe(), &response, sizeof(response)))
    return false;

  return false;
}

// static
DWORD __stdcall ExceptionHandlerServer::PipeServiceProc(void* ctx) {
  internal::PipeServiceContext* service_context =
      reinterpret_cast<internal::PipeServiceContext*>(ctx);
  DCHECK(service_context);

  for (;;) {
    bool ret = !!ConnectNamedPipe(service_context->pipe(), nullptr);
    if (!ret && GetLastError() != ERROR_PIPE_CONNECTED) {
      PLOG(ERROR) << "ConnectNamedPipe";
    } else if (ServiceClientConnection(*service_context)) {
      break;
    }
    DisconnectNamedPipe(service_context->pipe());
  }

  delete service_context;

  return 0;
}

// static
void __stdcall ExceptionHandlerServer::OnCrashDumpEvent(void* ctx, BOOLEAN) {
  // This function is executed on the thread pool.
  internal::ClientData* client = reinterpret_cast<internal::ClientData*>(ctx);
  base::AutoLock lock(*client->lock());

  // Capture the exception.
  unsigned int exit_code = client->delegate()->ExceptionHandlerServerException(
      client->process(),
      client->crash_exception_information_address(),
      client->debug_critical_section_address());

  SafeTerminateProcess(client->process(), exit_code);
}

// static
void __stdcall ExceptionHandlerServer::OnNonCrashDumpEvent(void* ctx, BOOLEAN) {
  // This function is executed on the thread pool.
  internal::ClientData* client = reinterpret_cast<internal::ClientData*>(ctx);
  base::AutoLock lock(*client->lock());

  // Capture the exception.
  client->delegate()->ExceptionHandlerServerException(
      client->process(),
      client->non_crash_exception_information_address(),
      client->debug_critical_section_address());

  bool result = !!SetEvent(client->non_crash_dump_completed_event());
  PLOG_IF(ERROR, !result) << "SetEvent";
}

// static
void __stdcall ExceptionHandlerServer::OnProcessEnd(void* ctx, BOOLEAN) {
  // This function is executed on the thread pool.
  internal::ClientData* client = reinterpret_cast<internal::ClientData*>(ctx);
  base::AutoLock lock(*client->lock());

  // Post back to the main thread to have it delete this client record.
  PostQueuedCompletionStatus(client->port(), 0, ULONG_PTR(client), nullptr);
}

}  // namespace crashpad
