// 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) {}

  PipeServiceContext(const PipeServiceContext&) = delete;
  PipeServiceContext& operator=(const PipeServiceContext&) = delete;

  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_;
};

//! \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(const ClientData&) = delete;
  ClientData& operator=(const ClientData&) = delete;

  ~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_;
};

}  // 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
