// 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/logging.h"
#include "base/numerics/safe_conversions.h"
#include "base/rand_util.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "minidump/minidump_file_writer.h"
#include "snapshot/crashpad_info_client_options.h"
#include "snapshot/win/process_snapshot_win.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
